blob: 87e150858e598c70cb698abdd0ac576e1707bdde [file]
// Copyright 2026 The Pigweed Authors
//
// 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 pw_status::{Error, Result};
use zerocopy::{FromBytes, Immutable, IntoBytes, TryFromBytes};
/// The type of request sent over the stream IPC channel.
#[non_exhaustive]
#[repr(u32)]
#[derive(Copy, Clone, Debug, IntoBytes, TryFromBytes, Immutable)]
pub enum RequestType {
/// Read data from the stream.
Read = 1,
/// Write data to the stream.
Write = 2,
}
/// Header prepended to all stream requests.
#[non_exhaustive]
#[repr(C)]
#[derive(IntoBytes, TryFromBytes, Immutable)]
pub struct RequestHeader {
/// The request command type.
pub request_type: RequestType,
}
impl RequestHeader {
/// Decodes a `RequestHeader` from a raw byte slice.
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
Self::try_from(bytes)
}
}
impl TryFrom<&[u8]> for RequestHeader {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self> {
if bytes.len() < core::mem::size_of::<RequestHeader>() {
return Err(Error::OutOfRange);
}
Self::try_read_from_bytes(&bytes[..core::mem::size_of::<RequestHeader>()])
.map_err(|_| Error::InvalidArgument)
}
}
/// Header prepended to all stream responses.
#[non_exhaustive]
#[repr(C)]
#[derive(IntoBytes, FromBytes, Immutable)]
pub struct ResponseHeader {
/// Status of the completed operation. `0` indicates success (OK).
/// A non-zero value represents a raw Pigweed error code.
pub status: u32,
/// For Read requests: the length of the payload following this header.
/// For Write requests: the number of bytes successfully written (supports partial writes).
pub length: u32,
}
impl TryFrom<&[u8]> for ResponseHeader {
type Error = Error;
fn try_from(bytes: &[u8]) -> Result<Self> {
if bytes.len() < core::mem::size_of::<ResponseHeader>() {
return Err(Error::OutOfRange);
}
Self::read_from_bytes(&bytes[..core::mem::size_of::<ResponseHeader>()])
.map_err(|_| Error::InvalidArgument)
}
}
impl ResponseHeader {
/// Decodes a `ResponseHeader` from a raw byte slice.
pub fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
Self::try_from(bytes)
}
/// Evaluates the status code in the response header, returning `Ok(())` on success,
/// or the corresponding Pigweed error.
pub fn result(&self) -> Result<()> {
pw_status::status_to_result(self.status)
}
}