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  }