github.com/cnotch/ipchub@v1.1.0/av/format/amf/primitive.go (about) 1 // Copyright (c) 2019,CAOHONGJU All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 5 package amf 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "io" 11 "math" 12 "time" 13 ) 14 15 // ReadBool . 16 func ReadBool(r io.Reader) (value bool, err error) { 17 var buff [1]byte 18 if _, err = io.ReadFull(r, buff[:]); err != nil { 19 return 20 } 21 22 marker := buff[0] 23 if TypeBoolean != marker { 24 err = fmt.Errorf("Amf0ReadBool: TypeBoolean != marker") 25 return 26 } 27 28 return readBool(r) 29 } 30 31 func readBool(r io.Reader) (value bool, err error) { 32 var buff [1]byte 33 if _, err = io.ReadFull(r, buff[:]); err != nil { 34 return 35 } 36 37 if buff[0] != 0 { 38 value = true 39 } else { 40 value = false 41 } 42 43 return 44 } 45 46 // WriteBool . 47 func WriteBool(w io.Writer, value bool) (err error) { 48 var buff [2]byte 49 50 buff[0] = TypeBoolean 51 if value { 52 buff[1] = 1 53 } else { 54 buff[1] = 0 55 } 56 _, err = w.Write(buff[:]) 57 return 58 } 59 60 // ReadNumber . 61 func ReadNumber(r io.Reader) (value float64, err error) { 62 var buff [1]byte 63 if _, err = io.ReadFull(r, buff[:]); err != nil { 64 return 65 } 66 67 marker := buff[0] 68 if TypeNumber != marker { 69 err = fmt.Errorf("Amf0ReadNumber: TypeNumber != marker") 70 return 71 } 72 73 return readNumber(r) 74 } 75 76 func readNumber(r io.Reader) (value float64, err error) { 77 var buff [8]byte 78 if _, err = io.ReadFull(r, buff[:]); err != nil { 79 return 80 } 81 82 valueTmp := binary.BigEndian.Uint64(buff[:]) 83 value = math.Float64frombits(valueTmp) 84 85 return 86 } 87 88 // WriteNumber . 89 func WriteNumber(w io.Writer, value float64) (err error) { 90 var buff [9]byte 91 92 buff[0] = TypeNumber 93 v2 := math.Float64bits(value) 94 binary.BigEndian.PutUint64(buff[1:], v2) 95 96 _, err = w.Write(buff[:]) 97 return 98 } 99 100 // ReadDate . 101 func ReadDate(r io.Reader) (value time.Time, err error) { 102 var buff [1]byte 103 if _, err = io.ReadFull(r, buff[:]); err != nil { 104 return 105 } 106 107 if TypeDate != buff[0] { 108 err = fmt.Errorf("Amf0ReadDate: TypeDate != marker") 109 return 110 } 111 112 return readDate(r) 113 } 114 115 func readDate(r io.Reader) (value time.Time, err error) { 116 var buff [10]byte 117 if _, err = io.ReadFull(r, buff[:]); err != nil { 118 return 119 } 120 121 valueTmp := binary.BigEndian.Uint64(buff[:8]) 122 nano := math.Float64frombits(valueTmp) * float64(time.Millisecond) 123 value = time.Unix(0, int64(nano)) 124 return 125 } 126 127 // WriteDate . 128 func WriteDate(w io.Writer, value time.Time) (err error) { 129 var buff [11]byte // 1+8+2 130 buff[0] = TypeDate 131 nano := value.UnixNano() 132 v2 := math.Float64bits(float64(nano) / float64(time.Millisecond)) 133 binary.BigEndian.PutUint64(buff[1:], v2) 134 _, err = w.Write(buff[:]) 135 return 136 } 137 138 // ReadString . 139 func ReadString(r io.Reader) (value string, err error) { 140 var buff [1]byte 141 if _, err = io.ReadFull(r, buff[:]); err != nil { 142 return 143 } 144 if TypeString != buff[0] { 145 err = fmt.Errorf("Amf0ReadString: TypeString != marker") 146 return 147 } 148 return readUtf8(r, 2) 149 } 150 151 // WriteString . 152 func WriteString(w io.Writer, value string) (err error) { 153 var buff [1]byte 154 buff[0] = TypeString 155 if _, err = w.Write(buff[:]); err != nil { 156 return 157 } 158 159 return writeUtf8(w, value, 2) 160 } 161 162 // ReadLongString . 163 func ReadLongString(r io.Reader) (value string, err error) { 164 var buff [1]byte 165 if _, err = io.ReadFull(r, buff[:]); err != nil { 166 return 167 } 168 if TypeLongString != buff[0] { 169 err = fmt.Errorf("Amf0ReadLongString: TypeLongString != marker") 170 return 171 } 172 return readUtf8(r, 4) 173 } 174 175 // WriteLongString . 176 func WriteLongString(w io.Writer, value string) (err error) { 177 var buff [1]byte 178 buff[0] = TypeLongString 179 if _, err = w.Write(buff[:]); err != nil { 180 return 181 } 182 183 return writeUtf8(w, value, 4) 184 } 185 186 func writeType(w io.Writer, typ byte) (err error) { 187 var buff [1]byte 188 buff[0] = typ 189 _, err = w.Write(buff[:]) 190 return 191 } 192 193 func readUtf8(r io.Reader, lenSize byte) (value string, err error) { 194 var buff [4]byte 195 if _, err = io.ReadFull(r, buff[4-lenSize:]); err != nil { 196 return 197 } 198 199 strLen := binary.BigEndian.Uint32(buff[:]) 200 if 0 == strLen { 201 return 202 } 203 204 valueBytes := make([]byte, strLen) 205 if _, err = io.ReadFull(r, valueBytes); err != nil { 206 return 207 } 208 value = string(valueBytes) 209 210 return 211 } 212 213 func writeUtf8(w io.Writer, value string, lenSize byte) (err error) { 214 var buff [4]byte 215 binary.BigEndian.PutUint32(buff[:], uint32(len(value))) 216 if _, err = w.Write(buff[4-lenSize:]); err != nil { 217 return 218 } 219 220 if ws, ok := w.(io.StringWriter); ok { 221 _, err = ws.WriteString(value) 222 } else { 223 _, err = w.Write([]byte(value)) 224 } 225 return 226 }