s2n-quic-platform 0.88.0

Internal crate used by s2n-quic
Documentation
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use super::{instruction::Dialect, Instruction};
use core::{fmt, mem::size_of};
use libc::sock_fprog;
use std::{io, os::fd::AsRawFd};

pub struct Program<'a, D: Dialect> {
    instructions: &'a [Instruction<D>],
}

impl<'a, D: Dialect> Program<'a, D> {
    #[inline]
    pub const fn new(instructions: &'a [Instruction<D>]) -> Self {
        if instructions.len() > D::MAX_INSTRUCTIONS {
            panic!("program too large");
        }
        Self { instructions }
    }

    #[inline]
    pub fn attach<S: AsRawFd>(&self, socket: &S) -> io::Result<()> {
        let prog = sock_fprog {
            filter: self.instructions.as_ptr() as *const _ as *mut _,
            len: self.instructions.len() as _,
        };

        let ret = unsafe {
            libc::setsockopt(
                socket.as_raw_fd(),
                libc::SOL_SOCKET,
                D::SOCKOPT as _,
                &prog as *const _ as *const _,
                size_of::<sock_fprog>() as _,
            )
        };

        if ret < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }
}

impl<D: Dialect> fmt::Debug for Program<'_, D> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Program")
            .field("instructions", &self.instructions)
            .finish()
    }
}

impl<D: Dialect> fmt::Display for Program<'_, D> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for (idx, inst) in self.instructions.iter().enumerate() {
            D::display(inst, f, Some(idx))?;
            writeln!(f)?;
        }
        Ok(())
    }
}