mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-22 15:11:02 +00:00
112 lines
2.6 KiB
Go
112 lines
2.6 KiB
Go
package internal
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
|
|
"golang.org/x/text/language"
|
|
)
|
|
|
|
// UnmarshalFunc unmarshals data into v.
|
|
type UnmarshalFunc func(data []byte, v interface{}) error
|
|
|
|
// MessageFile represents a parsed message file.
|
|
type MessageFile struct {
|
|
Path string
|
|
Tag language.Tag
|
|
Format string
|
|
Messages []*Message
|
|
}
|
|
|
|
// ParseMessageFileBytes returns the messages parsed from file.
|
|
func ParseMessageFileBytes(buf []byte, path string, unmarshalFuncs map[string]UnmarshalFunc) (*MessageFile, error) {
|
|
lang, format := parsePath(path)
|
|
tag := language.Make(lang)
|
|
messageFile := &MessageFile{
|
|
Path: path,
|
|
Tag: tag,
|
|
Format: format,
|
|
}
|
|
if len(buf) == 0 {
|
|
return messageFile, nil
|
|
}
|
|
unmarshalFunc := unmarshalFuncs[messageFile.Format]
|
|
if unmarshalFunc == nil {
|
|
if messageFile.Format == "json" {
|
|
unmarshalFunc = json.Unmarshal
|
|
} else {
|
|
return nil, fmt.Errorf("no unmarshaler registered for %s", messageFile.Format)
|
|
}
|
|
}
|
|
var raw interface{}
|
|
if err := unmarshalFunc(buf, &raw); err != nil {
|
|
return nil, err
|
|
}
|
|
switch data := raw.(type) {
|
|
case map[string]interface{}:
|
|
messageFile.Messages = make([]*Message, 0, len(data))
|
|
for id, data := range data {
|
|
m, err := NewMessage(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
m.ID = id
|
|
messageFile.Messages = append(messageFile.Messages, m)
|
|
}
|
|
case map[interface{}]interface{}:
|
|
messageFile.Messages = make([]*Message, 0, len(data))
|
|
for id, data := range data {
|
|
strid, ok := id.(string)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected key to be string but got %#v", id)
|
|
}
|
|
m, err := NewMessage(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
m.ID = strid
|
|
messageFile.Messages = append(messageFile.Messages, m)
|
|
}
|
|
case []interface{}:
|
|
// Backward compatibility for v1 file format.
|
|
messageFile.Messages = make([]*Message, 0, len(data))
|
|
for _, data := range data {
|
|
m, err := NewMessage(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
messageFile.Messages = append(messageFile.Messages, m)
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("unsupported file format %T", raw)
|
|
}
|
|
return messageFile, nil
|
|
}
|
|
|
|
func parsePath(path string) (langTag, format string) {
|
|
formatStartIdx := -1
|
|
for i := len(path) - 1; i >= 0; i-- {
|
|
c := path[i]
|
|
if os.IsPathSeparator(c) {
|
|
if formatStartIdx != -1 {
|
|
langTag = path[i+1 : formatStartIdx]
|
|
}
|
|
return
|
|
}
|
|
if path[i] == '.' {
|
|
if formatStartIdx != -1 {
|
|
langTag = path[i+1 : formatStartIdx]
|
|
return
|
|
}
|
|
if formatStartIdx == -1 {
|
|
format = path[i+1:]
|
|
formatStartIdx = i
|
|
}
|
|
}
|
|
}
|
|
if formatStartIdx != -1 {
|
|
langTag = path[:formatStartIdx]
|
|
}
|
|
return
|
|
}
|