Files
fontvielle e2720c09f7 refactor(nsdxml): заменить собственный кодек CP1251 на golang.org/x/text/encoding/charmap
После добавления NO_PROXY в bash-окружение (proxy.golang.org,
goproxy.cn, *.golang.org, github.com и пр.) штатные модули Go стали
доступны напрямую — zetit-прокси теперь обходится только для
внутренних/публичных хостов, которым нужен внутренний прокси, и
пропускает только нужное.

Заменено:
- internal/nsdxml/codec.go: 90+ строк собственной CP1251-таблицы →
  тонкая обёртка над golang.org/x/text/encoding/charmap.Windows1251
- go.mod: добавлен require golang.org/x/text v0.22.0
- internal/nsdxml/README.md: пометка о причине истории и текущей реализации

Покрытие nsdxml сохранилось, make ci зелёный.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:49:39 +03:00

70 lines
2.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package nsdxml
import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"io"
"strings"
"golang.org/x/text/encoding/charmap"
)
// xmlProlog — пролог windows-1251 XML, который мы пишем при сериализации.
const xmlProlog = `<?xml version="1.0" encoding="windows-1251"?>` + "\n"
// ErrUnmappable возвращается, когда руна не имеет представления в windows-1251.
var ErrUnmappable = errors.New("nsdxml: rune не представим в windows-1251")
// DecodeWindows1251 преобразует байты в кодировке windows-1251 в UTF-8.
// Использует штатную реализацию golang.org/x/text/encoding/charmap.
func DecodeWindows1251(src []byte) []byte {
out, _ := charmap.Windows1251.NewDecoder().Bytes(src)
return out
}
// EncodeWindows1251 преобразует UTF-8 байты в windows-1251. Если в
// исходной строке встречается руна, не выразимая в CP1251, возвращает
// ErrUnmappable с указанием смещения.
func EncodeWindows1251(src []byte) ([]byte, error) {
out, err := charmap.Windows1251.NewEncoder().Bytes(src)
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrUnmappable, err)
}
return out, nil
}
// CharsetReader пригоден к использованию в xml.Decoder.CharsetReader.
// Для charset "windows-1251"/"cp1251" возвращает декодирующий reader.
// Для UTF-8 и неуказанного charset — пробрасывает поток без изменений.
func CharsetReader(charset string, input io.Reader) (io.Reader, error) {
switch strings.ToLower(charset) {
case "windows-1251", "cp1251":
return charmap.Windows1251.NewDecoder().Reader(input), nil
case "", "utf-8", "utf8":
return input, nil
}
return nil, fmt.Errorf("nsdxml: неизвестная кодировка %q", charset)
}
// Marshal сериализует v в XML, добавляет пролог с encoding="windows-1251"
// и преобразует поток в windows-1251.
func Marshal(v any) ([]byte, error) {
utf8Body, err := xml.MarshalIndent(v, "", "\t")
if err != nil {
return nil, err
}
withProlog := append([]byte(xmlProlog), utf8Body...)
return EncodeWindows1251(withProlog)
}
// Unmarshal разбирает XML (windows-1251 или UTF-8) в v. Использует
// CharsetReader для перекодирования входа, если в прологе указана
// windows-1251.
func Unmarshal(data []byte, v any) error {
dec := xml.NewDecoder(bytes.NewReader(data))
dec.CharsetReader = CharsetReader
return dec.Decode(v)
}