diff options
Diffstat (limited to 'object/tree/mode/parse.go')
| -rw-r--r-- | object/tree/mode/parse.go | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/object/tree/mode/parse.go b/object/tree/mode/parse.go new file mode 100644 index 00000000..7839a89a --- /dev/null +++ b/object/tree/mode/parse.go @@ -0,0 +1,43 @@ +package mode + +import ( + "errors" + "fmt" +) + +// ErrInvalidMode indicates a malformed or unsupported tree entry mode. +var ErrInvalidMode = errors.New("object/tree/mode: invalid mode") + +// Parse decodes a canonical octal tree entry mode. +// +// It accepts only the modes Git itself writes +// and rejects malformed, unsupported, and zero-padded encodings. +func Parse(raw []byte) (Mode, error) { + if len(raw) == 0 { + return 0, fmt.Errorf("%w: empty mode", ErrInvalidMode) + } + + if raw[0] == '0' { + return 0, fmt.Errorf("%w: zero-padded mode %q", ErrInvalidMode, raw) + } + + if len(raw) > maxModeDigits { + return 0, fmt.Errorf("%w: mode %q too long", ErrInvalidMode, raw) + } + + var mode Mode + + for _, c := range raw { + if c < '0' || c > '7' { + return 0, fmt.Errorf("%w: non-octal byte in mode %q", ErrInvalidMode, raw) + } + + mode = mode<<3 | Mode(c-'0') + } + + if !mode.IsValid() { + return 0, fmt.Errorf("%w: unsupported mode %q", ErrInvalidMode, raw) + } + + return mode, nil +} |
