orchestra-toolkit 0.6.1

Client to interract with Orchestra system, uses HGTP protocol
Documentation
/* Copyright 2024-2025 LEDR Technologies Inc.
* This file is part of the Orchestra library, which helps developer use our Orchestra technology which is based on AvesTerra, owned and developped by Georgetown University, under license agreement with LEDR Technologies Inc.
*
* The Orchestra library is a free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.
*
* The Orchestra library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with the Orchestra library. If not, see <https://www.gnu.org/licenses/>.
*
* If you have any questions, feedback or issues about the Orchestra library, you can contact us at support@ledr.io.
*/

use time::OffsetDateTime;

use super::HGTPMessage;
use crate::{taxonomy::*, AvesterraError, Entity, String255, Token, Value};

impl HGTPMessage {
    pub fn pack_command(&mut self, value: Command) {
        self.frame[0..2].copy_from_slice(&(value as u16).to_le_bytes());
    }

    // Consider using `pack_error`
    pub fn pack_error_code(&mut self, value: HGTPError) {
        self.frame[2..4].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_version(&mut self, value: u16) {
        self.frame[4..6].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_report(&mut self, value: Report) {
        self.frame[6..8].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_method(&mut self, value: Method) {
        self.frame[8..10].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_attribute(&mut self, value: Attribute) {
        self.frame[10..12].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_event(&mut self, value: Event) {
        self.frame[12..14].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_mode(&mut self, value: Mode) {
        self.frame[14..16].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_category(&mut self, value: Category) {
        self.frame[16..18].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_class(&mut self, value: Class) {
        self.frame[18..20].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_context(&mut self, value: Context) {
        self.frame[20..22].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_aspect(&mut self, value: Aspect) {
        self.frame[22..24].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_state(&mut self, value: State) {
        self.frame[24..26].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_precedence(&mut self, value: u16) {
        self.frame[26..28].copy_from_slice(&value.to_le_bytes());
    }

    // You probably want to use `pack_value`
    pub fn pack_tag(&mut self, value: Tag) {
        self.frame[28..30].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_condition(&mut self, value: Condition) {
        self.frame[30..32].copy_from_slice(&(value as u16).to_le_bytes());
    }

    pub fn pack_instance(&mut self, value: i32) {
        self.frame[32..36].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_offset(&mut self, value: i32) {
        self.frame[36..40].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_time(&mut self, value: OffsetDateTime) {
        self.frame[40..48].copy_from_slice(&value.unix_timestamp().to_le_bytes());
    }

    pub fn pack_index(&mut self, value: i64) {
        self.frame[48..56].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_count(&mut self, value: i64) {
        self.frame[56..64].copy_from_slice(&value.to_le_bytes());
    }

    fn pack_extension(&mut self, value: i64) {
        self.frame[64..72].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_parameter(&mut self, value: i64) {
        self.frame[72..80].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_resultant(&mut self, value: i64) {
        self.frame[80..88].copy_from_slice(&value.to_le_bytes());
    }

    pub fn pack_timeout(&mut self, value: i64) {
        // Looking at the Ada implementation, the valid range is
        // type timeout_type      is new integer range 0..2**31-1;
        // so it could be a i32, but it is written as 64 bits in the HGTP frame.
        self.frame[88..96].copy_from_slice(&value.to_le_bytes());
    }

    // -- 64 reserved bytes --

    pub fn pack_entity(&mut self, value: Entity) {
        self.frame[160..164].copy_from_slice(&value.pid.to_le_bytes());
        self.frame[164..168].copy_from_slice(&value.hid.to_le_bytes());
        self.frame[168..176].copy_from_slice(&value.uid.to_le_bytes());
    }

    pub fn pack_outlet(&mut self, value: Entity) {
        self.frame[176..180].copy_from_slice(&value.pid.to_le_bytes());
        self.frame[180..184].copy_from_slice(&value.hid.to_le_bytes());
        self.frame[184..192].copy_from_slice(&value.uid.to_le_bytes());
    }

    pub fn pack_auxiliary(&mut self, value: Entity) {
        self.frame[192..196].copy_from_slice(&value.pid.to_le_bytes());
        self.frame[196..200].copy_from_slice(&value.hid.to_le_bytes());
        self.frame[200..208].copy_from_slice(&value.uid.to_le_bytes());
    }

    pub fn pack_ancillary(&mut self, value: Entity) {
        self.frame[208..212].copy_from_slice(&value.pid.to_le_bytes());
        self.frame[212..216].copy_from_slice(&value.hid.to_le_bytes());
        self.frame[216..224].copy_from_slice(&value.uid.to_le_bytes());
    }

    pub fn pack_authorization(&mut self, value: Token) {
        self.frame[224..240].copy_from_slice(value.as_bytes());
    }

    pub fn pack_authority(&mut self, value: Token) {
        self.frame[240..256].copy_from_slice(value.as_bytes());
    }

    pub fn pack_name(&mut self, value: String255) {
        let bytes = value.as_bytes();
        self.frame[256] = bytes.len() as u8;
        self.frame[257..257 + bytes.len()].copy_from_slice(bytes);
        self.frame[257 + bytes.len()..512].fill(0x00);
    }

    pub fn pack_key(&mut self, value: String255) {
        let bytes = value.as_bytes();
        self.frame[512] = bytes.len() as u8;
        self.frame[513..513 + bytes.len()].copy_from_slice(bytes);
        self.frame[513 + bytes.len()..768].fill(0x00);
    }

    // You probably want to use `pack_value` or `pack_error`
    pub fn pack_bytes(&mut self, value: &[u8]) {
        if value.len() <= 255 {
            self.pack_extension(0);
            self.frame[768] = value.len() as u8;
            self.frame[769..769 + value.len()].copy_from_slice(value);
            self.frame[769 + value.len()..1024].fill(0x00);
        } else {
            self.pack_extension(value.len() as i64);
            self.frame[768..1024].fill(0x00);
            self.unbounded.extend_from_slice(value);
        }
    }

    pub fn pack_value(&mut self, value: &Value) {
        self.pack_tag(value.get_tag());
        self.pack_bytes(value.get_bytes().as_bytes());
    }

    pub fn pack_error(&mut self, err: &AvesterraError) {
        self.pack_error_code(err.errcode);
        self.pack_bytes(err.message.as_bytes());
    }
}