github.com/iDigitalFlame/xmt@v0.5.4/data/chunk_writer.go (about)

     1  // Copyright (C) 2020 - 2023 iDigitalFlame
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU General Public License as published by
     5  // the Free Software Foundation, either version 3 of the License, or
     6  // any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU General Public License
    14  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    15  //
    16  
    17  package data
    18  
    19  import "io"
    20  
    21  // WriteInt writes the supplied value to the Chunk payload buffer.
    22  //
    23  // If this function returns 'ErrLimit' this indicates that the write was NOT
    24  // preformed.
    25  func (c *Chunk) WriteInt(n int) error {
    26  	return c.WriteUint64(uint64(n))
    27  }
    28  
    29  // WriteUint writes the supplied value to the Chunk payload buffer.
    30  //
    31  // If this function returns 'ErrLimit' this indicates that the write was NOT
    32  // preformed.
    33  func (c *Chunk) WriteUint(n uint) error {
    34  	return c.WriteUint64(uint64(n))
    35  }
    36  
    37  // WriteInt8 writes the supplied value to the Chunk payload buffer.
    38  //
    39  // If this function returns 'ErrLimit' this indicates that the write was NOT
    40  // preformed.
    41  func (c *Chunk) WriteInt8(n int8) error {
    42  	return c.WriteUint8(uint8(n))
    43  }
    44  
    45  // WriteBool writes the supplied value to the Chunk payload buffer.
    46  //
    47  // If this function returns 'ErrLimit' this indicates that the write was NOT
    48  // preformed.
    49  func (c *Chunk) WriteBool(b bool) error {
    50  	if b {
    51  		return c.WriteUint8(1)
    52  	}
    53  	return c.WriteUint8(0)
    54  }
    55  
    56  // WriteInt16 writes the supplied value to the Chunk payload buffer.
    57  //
    58  // If this function returns 'ErrLimit' this indicates that the write was NOT
    59  // preformed.
    60  func (c *Chunk) WriteInt16(n int16) error {
    61  	return c.WriteUint16(uint16(n))
    62  }
    63  
    64  // WriteInt32 writes the supplied value to the Chunk payload buffer.
    65  //
    66  // If this function returns 'ErrLimit' this indicates that the write was NOT
    67  // preformed.
    68  func (c *Chunk) WriteInt32(n int32) error {
    69  	return c.WriteUint32(uint32(n))
    70  }
    71  
    72  // WriteInt64 writes the supplied value to the Chunk payload buffer.
    73  //
    74  // If this function returns 'ErrLimit' this indicates that the write was NOT
    75  // preformed.
    76  func (c *Chunk) WriteInt64(n int64) error {
    77  	return c.WriteUint64(uint64(n))
    78  }
    79  
    80  // WriteUint8 writes the supplied value to the Chunk payload buffer.
    81  //
    82  // If this function returns 'ErrLimit' this indicates that the write was NOT
    83  // preformed.
    84  func (c *Chunk) WriteUint8(n uint8) error {
    85  	i, err := c.checkWriteSize(1)
    86  	if i == -1 {
    87  		return err
    88  	}
    89  	_ = c.buf[i]
    90  	c.buf[i] = n
    91  	return err
    92  }
    93  
    94  // WriteBytes writes the supplied value to the Chunk payload buffer.
    95  func (c *Chunk) WriteBytes(b []byte) error {
    96  	i, err := c.checkWriteSize(1)
    97  	if i == -1 {
    98  		return err
    99  	}
   100  	var x int
   101  	switch l := uint64(len(b)); {
   102  	case l == 0:
   103  		_ = c.buf[i]
   104  		c.buf[i] = 0
   105  		return err
   106  	case l < LimitSmall:
   107  		if x, err = c.checkWriteSize(1 + int(l)); x == -1 {
   108  			return err
   109  		}
   110  		_, x = c.buf[i+1+int(l)], x+1
   111  		c.buf[i], c.buf[i+1] = 1, byte(l)
   112  	case l < LimitMedium:
   113  		if x, err = c.checkWriteSize(2 + int(l)); x == -1 {
   114  			return err
   115  		}
   116  		_, x = c.buf[i+2+int(l)], x+2
   117  		c.buf[i], c.buf[i+1], c.buf[i+2] = 3, byte(l>>8), byte(l)
   118  	case l < LimitLarge:
   119  		if x, err = c.checkWriteSize(4 + int(l)); x == -1 {
   120  			return err
   121  		}
   122  		_, x = c.buf[i+4+int(l)], x+4
   123  		c.buf[i], c.buf[i+1], c.buf[i+2] = 5, byte(l>>24), byte(l>>16)
   124  		c.buf[i+3], c.buf[i+4] = byte(l>>8), byte(l)
   125  	default:
   126  		if x, err = c.checkWriteSize(8 + int(l)); x == -1 {
   127  			return err
   128  		}
   129  		_, x = c.buf[i+8+int(l)], x+8
   130  		c.buf[i], c.buf[i+1], c.buf[i+2] = 7, byte(l>>56), byte(l>>48)
   131  		c.buf[i+3], c.buf[i+4] = byte(l>>40), byte(l>>32)
   132  		c.buf[i+5], c.buf[i+6] = byte(l>>24), byte(l>>16)
   133  		c.buf[i+7], c.buf[i+8] = byte(l>>8), byte(l)
   134  	}
   135  	if n := copy(c.buf[x:], b); n != len(b) {
   136  		return io.ErrShortWrite
   137  	}
   138  	return err
   139  }
   140  
   141  // WriteUint16 writes the supplied value to the Chunk payload buffer.
   142  //
   143  // If this function returns 'ErrLimit' this indicates that the write was NOT
   144  // preformed.
   145  func (c *Chunk) WriteUint16(n uint16) error {
   146  	i, err := c.checkWriteSize(2)
   147  	if i == -1 {
   148  		return err
   149  	}
   150  	_ = c.buf[i+1]
   151  	c.buf[i], c.buf[i+1] = byte(n>>8), byte(n)
   152  	return err
   153  }
   154  
   155  // WriteUint32 writes the supplied value to the Chunk payload buffer.
   156  //
   157  // If this function returns 'ErrLimit' this indicates that the write was NOT
   158  // preformed.
   159  func (c *Chunk) WriteUint32(n uint32) error {
   160  	i, err := c.checkWriteSize(4)
   161  	if i == -1 {
   162  		return err
   163  	}
   164  	_ = c.buf[i+3]
   165  	c.buf[i], c.buf[i+1] = byte(n>>24), byte(n>>16)
   166  	c.buf[i+2], c.buf[i+3] = byte(n>>8), byte(n)
   167  	return err
   168  }
   169  
   170  // WriteUint64 writes the supplied value to the Chunk payload buffer.
   171  //
   172  // If this function returns 'ErrLimit' this indicates that the write was NOT
   173  // preformed.
   174  func (c *Chunk) WriteUint64(n uint64) error {
   175  	i, err := c.checkWriteSize(8)
   176  	if i == -1 {
   177  		return err
   178  	}
   179  	_ = c.buf[i+7]
   180  	c.buf[i], c.buf[i+1] = byte(n>>56), byte(n>>48)
   181  	c.buf[i+2], c.buf[i+3] = byte(n>>40), byte(n>>32)
   182  	c.buf[i+4], c.buf[i+5] = byte(n>>24), byte(n>>16)
   183  	c.buf[i+6], c.buf[i+7] = byte(n>>8), byte(n)
   184  	return err
   185  }
   186  
   187  // WriteString writes the supplied value to the Chunk payload buffer.
   188  //
   189  // If this function returns 'ErrLimit' this indicates that the write was NOT
   190  // preformed.
   191  func (c *Chunk) WriteString(s string) error {
   192  	return c.WriteBytes([]byte(s))
   193  }
   194  
   195  // WriteFloat32 writes the supplied value to the Chunk payload buffer.
   196  //
   197  // If this function returns 'ErrLimit' this indicates that the write was NOT
   198  // preformed.
   199  func (c *Chunk) WriteFloat32(f float32) error {
   200  	return c.WriteUint32(float32ToInt(f))
   201  }
   202  
   203  // WriteFloat64 writes the supplied value to the Chunk payload buffer.
   204  //
   205  // If this function returns 'ErrLimit' this indicates that the write was NOT
   206  // preformed.
   207  func (c *Chunk) WriteFloat64(f float64) error {
   208  	return c.WriteUint64(float64ToInt(f))
   209  }
   210  
   211  // WriteBoolPos writes the supplied boolean value to the Chunk payload buffer at
   212  // the supplied index 'p'.
   213  //
   214  // The error 'io.EOF' is returned if the position specified is greater than the
   215  // Chunk buffer size, or 'ErrLimit' if this position is greater than the set
   216  // Chunk limit.
   217  func (c *Chunk) WriteBoolPos(p int, b bool) error {
   218  	if p >= c.Size() {
   219  		return io.EOF
   220  	}
   221  	if c.Limit > 0 && p >= c.Limit {
   222  		return ErrLimit
   223  	}
   224  	if _ = c.buf[p]; b {
   225  		c.buf[p] = 1
   226  	} else {
   227  		c.buf[p] = 0
   228  	}
   229  	return nil
   230  }
   231  func (c *Chunk) checkWriteSize(n int) (int, error) {
   232  	if c.Limit > 0 && !c.Available(n) {
   233  		return -1, ErrLimit
   234  	}
   235  	i, err := c.quickSlice(n)
   236  	switch {
   237  	case i == 0 && err != nil:
   238  		return -1, err
   239  	case c.Limit <= 0 && c.Size() < i+n:
   240  		return -1, io.ErrShortWrite
   241  	}
   242  	return i, err
   243  }
   244  
   245  // WriteUint8Pos writes the supplied uint8 value to the Chunk payload buffer at
   246  // the supplied index 'p'.
   247  //
   248  // The error 'io.EOF' is returned if the position specified is greater than the
   249  // Chunk buffer size, or 'ErrLimit' if this position is greater than the set
   250  // Chunk limit.
   251  func (c *Chunk) WriteUint8Pos(p int, n uint8) error {
   252  	if p >= c.Size() {
   253  		return io.EOF
   254  	}
   255  	if c.Limit > 0 && p >= c.Limit {
   256  		return ErrLimit
   257  	}
   258  	_ = c.buf[p]
   259  	c.buf[p] = n
   260  	return nil
   261  }
   262  
   263  // WriteUint16Pos writes the supplied uint16 value to the Chunk payload buffer
   264  // at the supplied index 'p'.
   265  //
   266  // The error 'io.EOF' is returned if the position specified is greater than the
   267  // Chunk buffer size, or 'ErrLimit' if this position is greater than the set
   268  // Chunk limit.
   269  func (c *Chunk) WriteUint16Pos(p int, n uint16) error {
   270  	if p >= c.Size() || p+1 >= c.Size() {
   271  		return io.EOF
   272  	}
   273  	if c.Limit > 0 && (p >= c.Limit || p+1 >= c.Limit) {
   274  		return ErrLimit
   275  	}
   276  	_ = c.buf[p+1]
   277  	c.buf[p], c.buf[p+1] = byte(n>>8), byte(n)
   278  	return nil
   279  }
   280  
   281  // WriteUint32Pos writes the supplied uint16 value to the Chunk payload buffer
   282  // at the supplied index 'p'.
   283  //
   284  // The error 'io.EOF' is returned if the position specified is greater than the
   285  // Chunk buffer size, or 'ErrLimit' if this position is greater than the set
   286  // Chunk limit.
   287  func (c *Chunk) WriteUint32Pos(p int, n uint32) error {
   288  	if p >= c.Size() || p+3 >= c.Size() {
   289  		return io.EOF
   290  	}
   291  	if c.Limit > 0 && (p >= c.Limit || p+3 >= c.Limit) {
   292  		return ErrLimit
   293  	}
   294  	_ = c.buf[p+3]
   295  	c.buf[p], c.buf[p+1], c.buf[p+2], c.buf[p+3] = byte(n>>24), byte(n>>16), byte(n>>8), byte(n)
   296  	return nil
   297  }
   298  
   299  // WriteUint64Pos writes the supplied uint16 value to the Chunk payload buffer
   300  // at the supplied index 'p'.
   301  //
   302  // The error 'io.EOF' is returned if the position specified is greater than the
   303  // Chunk buffer size, or 'ErrLimit' if this position is greater than the set
   304  // Chunk limit.
   305  func (c *Chunk) WriteUint64Pos(p int, n uint64) error {
   306  	if p >= c.Size() || p+7 >= c.Size() {
   307  		return io.EOF
   308  	}
   309  	if c.Limit > 0 && (p >= c.Limit || p+7 >= c.Limit) {
   310  		return ErrLimit
   311  	}
   312  	_ = c.buf[p+7]
   313  	c.buf[p], c.buf[p+1], c.buf[p+2], c.buf[p+3] = byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32)
   314  	c.buf[p+4], c.buf[p+5], c.buf[p+6], c.buf[p+7] = byte(n>>24), byte(n>>16), byte(n>>8), byte(n)
   315  	return nil
   316  }