121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
// Sshwifty - A Web SSH client
|
|
//
|
|
// Copyright (C) 2019-2022 Ni Rui <ranqus@gmail.com>
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
package commands
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/nirui/sshwifty/application/rw"
|
|
)
|
|
|
|
// Errors
|
|
var (
|
|
ErrIntegerMarshalNotEnoughBuffer = errors.New(
|
|
"not enough buffer to marshal the integer")
|
|
|
|
ErrIntegerMarshalTooLarge = errors.New(
|
|
"integer cannot be marshalled, because the vaule was too large")
|
|
)
|
|
|
|
// Integer is a 16bit unsigned integer data
|
|
//
|
|
// Format:
|
|
// +-------------------------------------+--------------+
|
|
// | 1 bit | 7 bits |
|
|
// +-------------------------------------+--------------+
|
|
// | 1 when current byte is the end byte | Integer data |
|
|
// +-------------------------------------+--------------+
|
|
//
|
|
// Example:
|
|
// - 00000000 00000000: 0
|
|
// - 01111111: 127
|
|
// - 11111111 01000000: 255
|
|
type Integer uint16
|
|
|
|
const (
|
|
integerHasNextBit = 0x80
|
|
integerValueCutter = 0x7f
|
|
)
|
|
|
|
// Consts
|
|
const (
|
|
MaxInteger = 0x3fff
|
|
MaxIntegerBytes = 2
|
|
)
|
|
|
|
// ByteSize returns how many bytes current integer will be encoded into
|
|
func (i *Integer) ByteSize() int {
|
|
if *i > integerValueCutter {
|
|
return 2
|
|
}
|
|
|
|
return 1
|
|
}
|
|
|
|
// Int returns a int of current Integer
|
|
func (i *Integer) Int() int {
|
|
return int(*i)
|
|
}
|
|
|
|
// Marshal build serialized data of the integer
|
|
func (i *Integer) Marshal(b []byte) (int, error) {
|
|
bLen := len(b)
|
|
|
|
if *i > MaxInteger {
|
|
return 0, ErrIntegerMarshalTooLarge
|
|
}
|
|
|
|
if bLen < i.ByteSize() {
|
|
return 0, ErrIntegerMarshalNotEnoughBuffer
|
|
}
|
|
|
|
if *i <= integerValueCutter {
|
|
b[0] = byte(*i & integerValueCutter)
|
|
|
|
return 1, nil
|
|
}
|
|
|
|
b[0] = byte((*i >> 7) | integerHasNextBit)
|
|
b[1] = byte(*i & integerValueCutter)
|
|
|
|
return 2, nil
|
|
}
|
|
|
|
// Unmarshal read data and parse the integer
|
|
func (i *Integer) Unmarshal(reader rw.ReaderFunc) error {
|
|
buf := [1]byte{}
|
|
|
|
for j := 0; j < MaxIntegerBytes; j++ {
|
|
_, rErr := rw.ReadFull(reader, buf[:])
|
|
|
|
if rErr != nil {
|
|
return rErr
|
|
}
|
|
|
|
*i |= Integer(buf[0] & integerValueCutter)
|
|
|
|
if integerHasNextBit&buf[0] == 0 {
|
|
return nil
|
|
}
|
|
|
|
*i <<= 7
|
|
}
|
|
|
|
return nil
|
|
}
|