github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/cmd/info/internal/internal.go (about) 1 package internal 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "strings" 8 ) 9 10 // Presence describes the presence of a filename in file listing 11 type Presence int 12 13 // Possible Presence states 14 const ( 15 Absent Presence = iota 16 Present 17 Renamed 18 Multiple 19 ) 20 21 // Position is the placement of the test character in the filename 22 type Position int 23 24 // Predefined positions 25 const ( 26 PositionMiddle Position = 1 << iota 27 PositionLeft 28 PositionRight 29 PositionNone Position = 0 30 PositionAll Position = PositionRight<<1 - 1 31 ) 32 33 // PositionList contains all valid positions 34 var PositionList = []Position{PositionMiddle, PositionLeft, PositionRight} 35 36 // ControlResult contains the result of a single character test 37 type ControlResult struct { 38 Text string `json:"-"` 39 WriteError map[Position]string 40 GetError map[Position]string 41 InList map[Position]Presence 42 } 43 44 // InfoReport is the structure of the JSON output 45 type InfoReport struct { 46 Remote string 47 ControlCharacters *map[string]ControlResult 48 MaxFileLength *int 49 CanStream *bool 50 CanWriteUnnormalized *bool 51 CanReadUnnormalized *bool 52 CanReadRenormalized *bool 53 } 54 55 func (e Position) String() string { 56 switch e { 57 case PositionNone: 58 return "none" 59 case PositionAll: 60 return "all" 61 } 62 var buf bytes.Buffer 63 if e&PositionMiddle != 0 { 64 buf.WriteString("middle") 65 e &= ^PositionMiddle 66 } 67 if e&PositionLeft != 0 { 68 if buf.Len() != 0 { 69 buf.WriteRune(',') 70 } 71 buf.WriteString("left") 72 e &= ^PositionLeft 73 } 74 if e&PositionRight != 0 { 75 if buf.Len() != 0 { 76 buf.WriteRune(',') 77 } 78 buf.WriteString("right") 79 e &= ^PositionRight 80 } 81 if e != PositionNone { 82 panic("invalid position") 83 } 84 return buf.String() 85 } 86 87 // MarshalText encodes the position when used as a map key 88 func (e Position) MarshalText() ([]byte, error) { 89 return []byte(e.String()), nil 90 } 91 92 // UnmarshalText decodes a position when used as a map key 93 func (e *Position) UnmarshalText(text []byte) error { 94 switch s := strings.ToLower(string(text)); s { 95 default: 96 *e = PositionNone 97 for _, p := range strings.Split(s, ",") { 98 switch p { 99 case "left": 100 *e |= PositionLeft 101 case "middle": 102 *e |= PositionMiddle 103 case "right": 104 *e |= PositionRight 105 default: 106 return fmt.Errorf("unknown position: %s", e) 107 } 108 } 109 case "none": 110 *e = PositionNone 111 case "all": 112 *e = PositionAll 113 } 114 return nil 115 } 116 117 func (e Presence) String() string { 118 switch e { 119 case Absent: 120 return "absent" 121 case Present: 122 return "present" 123 case Renamed: 124 return "renamed" 125 case Multiple: 126 return "multiple" 127 default: 128 panic("invalid presence") 129 } 130 } 131 132 // MarshalJSON encodes the presence when used as a JSON value 133 func (e Presence) MarshalJSON() ([]byte, error) { 134 return json.Marshal(e.String()) 135 } 136 137 // UnmarshalJSON decodes a presence when used as a JSON value 138 func (e *Presence) UnmarshalJSON(text []byte) error { 139 var s string 140 if err := json.Unmarshal(text, &s); err != nil { 141 return err 142 } 143 switch s := strings.ToLower(s); s { 144 case "absent": 145 *e = Absent 146 case "present": 147 *e = Present 148 case "renamed": 149 *e = Renamed 150 case "multiple": 151 *e = Multiple 152 default: 153 return fmt.Errorf("unknown presence: %s", e) 154 } 155 return nil 156 }