ctaphid 0.1.1

Rust implementation of the CTAPHID protocol
Documentation
// Copyright (C) 2021 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: Apache-2.0 or MIT

use std::cmp;

use crate::{
    command::Command,
    error::{Error, RequestError},
    hid::Device,
    packet,
    transaction::Channel,
};

pub fn send(
    device: &impl Device,
    channel: Channel,
    command: Command,
    data: &[u8],
    buffer: &mut [u8],
) -> Result<(), Error> {
    let data_size_init = packet::data_size_init(device);
    let data_size_cont = packet::data_size_cont(device);
    if data.len() > data_size_init + 128 * data_size_cont {
        return Err(Error::from(RequestError::DataTooLong));
    }
    let length = data.len() as u16;
    let n = cmp::min(data_size_init, data.len());
    let (data_init, data_cont) = data.split_at(n);
    packet::send_init(device, channel, command, length, data_init, buffer)?;

    for (sequence, data) in data_cont.chunks(data_size_cont).enumerate() {
        packet::send_cont(device, channel, sequence as u8, data, buffer)?;
    }

    Ok(())
}

pub fn receive(
    device: &impl Device,
    channel: Channel,
    command: Command,
    buffer: &mut [u8],
) -> Result<Vec<u8>, Error> {
    let (n, packet_data) = packet::receive_init(device, channel, command, buffer)?;
    let n = usize::from(n);
    let mut data: Vec<u8> = Vec::with_capacity(n);
    let m = std::cmp::min(packet_data.len(), n);
    data.extend_from_slice(&packet_data[..m]);

    let mut sequence = 0;
    while data.len() < n {
        let packet_data = packet::receive_cont(device, channel, sequence, buffer)?;
        let m = std::cmp::min(packet_data.len(), n - data.len());
        data.extend_from_slice(&packet_data[..m]);
        sequence += 1;
    }

    Ok(data)
}