blob: 16e7b4fdbcca4262d7ee7ea33da00ee98b1a717f [file] [log] [blame] [edit]
// Copyright 2023, Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Packet parsers and serializers.
/// UCI packet parser and serializer.
pub mod uci {
#![allow(clippy::all)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unused)]
#![allow(missing_docs)]
include!(concat!(env!("OUT_DIR"), "/uci_packets.rs"));
/// Size of common UCI packet header.
pub const COMMON_HEADER_SIZE: usize = 1;
/// Size of UCI packet headers.
pub const HEADER_SIZE: usize = 4;
/// Maximum size of an UCI control packet payload.
pub const MAX_CTRL_PACKET_PAYLOAD_SIZE: usize = 255;
/// Maximum size of an UCI data packet payload.
pub const MAX_DATA_PACKET_PAYLOAD_SIZE: usize = 1024;
// Extract the message type from the first 3 bits of the passed (header) byte
pub fn parse_message_type(byte: u8) -> MessageType {
MessageType::try_from((byte >> 5) & 0x7).unwrap_or(MessageType::Command)
}
/// Read a single UCI packet from a TCP read half.
/// This function does not reassemble segmented packets.
pub async fn read(
mut socket: tokio::net::tcp::OwnedReadHalf,
) -> Option<(Vec<u8>, tokio::net::tcp::OwnedReadHalf)> {
use tokio::io::AsyncReadExt;
let mut packet = vec![0; HEADER_SIZE];
// Read the common packet header.
socket.read_exact(&mut packet[0..HEADER_SIZE]).await.ok()?;
let common_packet_header =
CommonPacketHeader::parse(&packet[0..COMMON_HEADER_SIZE]).ok()?;
let payload_length = match common_packet_header.get_mt() {
MessageType::Data => {
let data_packet_header = DataPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?;
data_packet_header.get_payload_length() as usize
}
_ => {
let control_packet_header =
ControlPacketHeader::parse(&packet[0..HEADER_SIZE]).ok()?;
control_packet_header.get_payload_length() as usize
}
};
// Read the packet payload.
packet.resize(payload_length + HEADER_SIZE, 0);
socket.read_exact(&mut packet[HEADER_SIZE..]).await.ok()?;
Some((packet, socket))
}
/// Write a single UCI packet to a TCP write half.
/// This function accepts segmented packets only.
pub async fn write(
mut socket: tokio::net::tcp::OwnedWriteHalf,
packet: Vec<u8>,
) -> std::result::Result<tokio::net::tcp::OwnedWriteHalf, anyhow::Error> {
use tokio::io::AsyncWriteExt;
socket.write_all(&packet).await?;
Ok(socket)
}
}