sparrow-kata-full/apps/system/components/DebugConsole/zmodem/src/frame.rs
June Tate-Gans 1a068b0143 kata: Prepend the Google copyright and Apache 2.0 license
This includes adding it to TOML files and CAmkES assembly files.

Change-Id: I263e7a566df91fccc04f9b2186edab13331290c5
GitOrigin-RevId: 48a35b06ca868a0a4d379f881068cc4dad491669
2022-10-06 18:59:16 +00:00

185 lines
4.5 KiB
Rust

// Copyright 2022 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
//
// https://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.
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::fmt;
use consts::*;
use crc;
use hex::*;
use proto;
#[derive(Debug, Eq, PartialEq)]
pub struct Frame {
header: u8,
ftype: u8,
flags: [u8; 4],
}
impl Frame {
pub fn new(header: u8, ftype: u8) -> Frame {
Frame {
header,
ftype,
flags: [0; 4],
}
}
pub fn flags<'b>(&'b mut self, flags: &[u8; 4]) -> &'b mut Frame {
self.flags = *flags;
self
}
pub fn count<'b>(&'b mut self, count: u32) -> &'b mut Frame {
self.flags = [
(count >> 0) as u8,
(count >> 8) as u8,
(count >> 16) as u8,
(count >> 24) as u8,
];
self
}
pub fn get_count(&self) -> u32 {
(self.flags[3] as u32) << 24
| (self.flags[2] as u32) << 16
| (self.flags[1] as u32) << 8
| (self.flags[0] as u32)
}
pub fn build(&self) -> Vec<u8> {
let mut out = vec![ZPAD];
if self.header == ZHEX {
out.push(ZPAD);
}
out.push(ZLDE);
out.push(self.header);
out.push(self.ftype);
out.extend_from_slice(&self.flags);
let mut crc = get_crc(self.header, &out);
out.append(&mut crc);
if self.header == ZHEX {
let hex = out.drain(4..).collect::<Vec<u8>>().encode_hex::<String>();
out.extend_from_slice(hex.as_bytes());
}
let tmp = out.drain(3..).collect::<Vec<_>>();
let mut tmp2 = Vec::new();
proto::escape_buf(&tmp, &mut tmp2);
out.extend_from_slice(&tmp2);
if self.header == ZHEX {
out.extend_from_slice(b"\r\n");
if self.ftype != ZACK && self.ftype != ZFIN {
out.push(XON);
}
}
out
}
pub fn get_frame_type(&self) -> u8 { self.ftype }
pub fn get_header(&self) -> u8 { self.header }
}
fn get_crc(header: u8, buf: &[u8]) -> Vec<u8> {
let offset = match header {
ZHEX => 4,
_ => 3,
};
match header {
ZBIN32 => crc::get_crc32(&buf[offset..], None).into(),
_ => crc::get_crc16(&buf[offset..], None).into(),
}
}
impl fmt::Display for Frame {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let hdr = match self.header {
ZHEX => "ZHEX",
ZBIN => "ZBIN",
ZBIN32 => "ZBIN32",
_ => "???",
};
let ft = match self.ftype {
ZRQINIT => "ZRQINIT",
ZRINIT => "ZRINIT",
ZSINIT => "ZSINIT",
ZACK => "ZACK",
ZFILE => "ZFILE",
ZSKIP => "ZSKIP",
ZNAK => "ZNAK",
ZABORT => "ZABORT",
ZFIN => "ZFIN",
ZRPOS => "ZRPOS",
ZDATA => "ZDATA",
ZEOF => "ZEOF",
ZFERR => "ZFERR",
ZCRC => "ZCRC",
ZCHALLENGE => "ZCHALLENGE",
ZCOMPL => "ZCOMPL",
ZCAN => "ZCAN",
ZFREECNT => "ZFREECNT",
ZCOMMAND => "ZCOMMAND",
ZSTDERR => "ZSTDERR",
_ => "???",
};
write!(f, "{}({})", hdr, ft)
}
}
#[test]
fn test_frame() {
use alloc::vec;
assert_eq!(
Frame::new(ZBIN, 0).build(),
vec![ZPAD, ZLDE, ZBIN, 0, 0, 0, 0, 0, 0, 0]
);
assert_eq!(
Frame::new(ZBIN32, 0).build(),
vec![ZPAD, ZLDE, ZBIN32, 0, 0, 0, 0, 0, 29, 247, 34, 198]
);
assert_eq!(
Frame::new(ZBIN, 0).flags(&[1; 4]).build(),
vec![ZPAD, ZLDE, ZBIN, 0, 1, 1, 1, 1, 98, 148]
);
assert_eq!(
Frame::new(ZBIN, 0).flags(&[1; 4]).build(),
vec![ZPAD, ZLDE, ZBIN, 0, 1, 1, 1, 1, 98, 148]
);
assert_eq!(
Frame::new(ZHEX, 0).flags(&[1; 4]).build(),
vec![
ZPAD, ZPAD, ZLDE, ZHEX, b'0', b'0', b'0', b'1', b'0', b'1', b'0', b'1', b'0', b'1', 54,
50, 57, 52, b'\r', b'\n', XON
]
);
}