AUTOSAR SOME/IP: Rust parsing library

SOME/IP (Scalable service-Oriented MiddlewarE over IP) is an automotive/embedded communication protocol which supports remoteprocedure calls, event notifications and the underlying serialization/wire format.

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.9

This page hosts a formal specification of AUTOSAR SOME/IP using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Rust source code to parse AUTOSAR SOME/IP

some_ip.rs

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#![allow(unused_imports)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(irrefutable_let_patterns)]
#![allow(unused_comparisons)]

extern crate kaitai;
use kaitai::*;
use std::convert::{TryFrom, TryInto};
use std::cell::{Ref, Cell, RefCell};
use std::rc::{Rc, Weak};
use super::some_ip_sd::SomeIpSd;

/**
 * SOME/IP (Scalable service-Oriented MiddlewarE over IP) is an automotive/embedded
 * communication protocol which supports remoteprocedure calls, event notifications
 * and the underlying serialization/wire format.
 * \sa https://www.autosar.org/fileadmin/standards/foundation/19-11/AUTOSAR_PRS_SOMEIPProtocol.pdf Source
 */

#[derive(Default, Debug, Clone)]
pub struct SomeIp {
    pub _root: SharedType<SomeIp>,
    pub _parent: SharedType<SomeIp>,
    pub _self: SharedType<Self>,
    header: RefCell<OptRc<SomeIp_Header>>,
    payload: RefCell<Option<SomeIp_Payload>>,
    _io: RefCell<BytesReader>,
    payload_raw: RefCell<Vec<u8>>,
}
#[derive(Debug, Clone)]
pub enum SomeIp_Payload {
    SomeIpSd(OptRc<SomeIpSd>),
    Bytes(Vec<u8>),
}
impl From<&SomeIp_Payload> for OptRc<SomeIpSd> {
    fn from(v: &SomeIp_Payload) -> Self {
        if let SomeIp_Payload::SomeIpSd(x) = v {
            return x.clone();
        }
        panic!("expected SomeIp_Payload::SomeIpSd, got {:?}", v)
    }
}
impl From<OptRc<SomeIpSd>> for SomeIp_Payload {
    fn from(v: OptRc<SomeIpSd>) -> Self {
        Self::SomeIpSd(v)
    }
}
impl From<&SomeIp_Payload> for Vec<u8> {
    fn from(v: &SomeIp_Payload) -> Self {
        if let SomeIp_Payload::Bytes(x) = v {
            return x.clone();
        }
        panic!("expected SomeIp_Payload::Bytes, got {:?}", v)
    }
}
impl From<Vec<u8>> for SomeIp_Payload {
    fn from(v: Vec<u8>) -> Self {
        Self::Bytes(v)
    }
}
impl KStruct for SomeIp {
    type Root = SomeIp;
    type Parent = SomeIp;

    fn read<S: KStream>(
        self_rc: &OptRc<Self>,
        _io: &S,
        _root: SharedType<Self::Root>,
        _parent: SharedType<Self::Parent>,
    ) -> KResult<()> {
        *self_rc._io.borrow_mut() = _io.clone();
        self_rc._root.set(_root.get());
        self_rc._parent.set(_parent.get());
        self_rc._self.set(Ok(self_rc.clone()));
        let _rrc = self_rc._root.get_value().borrow().upgrade();
        let _prc = self_rc._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        let t = Self::read_into::<_, SomeIp_Header>(&*_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
        *self_rc.header.borrow_mut() = t;
        match *self_rc.header().message_id().value()? {
            4294934784 => {
                *self_rc.payload_raw.borrow_mut() = _io.read_bytes(((*self_rc.header().length() as u32) - (8 as u32)) as usize)?.into();
                let payload_raw = self_rc.payload_raw.borrow();
                let _t_payload_raw_io = BytesReader::from(payload_raw.clone());
                let t = Self::read_into::<BytesReader, SomeIpSd>(&_t_payload_raw_io, None, None)?.into();
                *self_rc.payload.borrow_mut() = Some(t);
            }
            _ => {
                *self_rc.payload.borrow_mut() = Some(_io.read_bytes(((*self_rc.header().length() as u32) - (8 as u32)) as usize)?.into());
            }
        }
        Ok(())
    }
}
impl SomeIp {
}
impl SomeIp {
    pub fn header(&self) -> Ref<'_, OptRc<SomeIp_Header>> {
        self.header.borrow()
    }
}
impl SomeIp {
    pub fn payload(&self) -> Ref<'_, Option<SomeIp_Payload>> {
        self.payload.borrow()
    }
}
impl SomeIp {
    pub fn _io(&self) -> Ref<'_, BytesReader> {
        self._io.borrow()
    }
}
impl SomeIp {
    pub fn payload_raw(&self) -> Ref<'_, Vec<u8>> {
        self.payload_raw.borrow()
    }
}

#[derive(Default, Debug, Clone)]
pub struct SomeIp_Header {
    pub _root: SharedType<SomeIp>,
    pub _parent: SharedType<SomeIp>,
    pub _self: SharedType<Self>,
    message_id: RefCell<OptRc<SomeIp_Header_MessageId>>,
    length: RefCell<u32>,
    request_id: RefCell<OptRc<SomeIp_Header_RequestId>>,
    protocol_version: RefCell<u8>,
    interface_version: RefCell<u8>,
    message_type: RefCell<SomeIp_Header_MessageTypeEnum>,
    return_code: RefCell<SomeIp_Header_ReturnCodeEnum>,
    _io: RefCell<BytesReader>,
    message_id_raw: RefCell<Vec<u8>>,
    request_id_raw: RefCell<Vec<u8>>,
    f_is_valid_service_discovery: Cell<bool>,
    is_valid_service_discovery: RefCell<bool>,
}
impl KStruct for SomeIp_Header {
    type Root = SomeIp;
    type Parent = SomeIp;

    fn read<S: KStream>(
        self_rc: &OptRc<Self>,
        _io: &S,
        _root: SharedType<Self::Root>,
        _parent: SharedType<Self::Parent>,
    ) -> KResult<()> {
        *self_rc._io.borrow_mut() = _io.clone();
        self_rc._root.set(_root.get());
        self_rc._parent.set(_parent.get());
        self_rc._self.set(Ok(self_rc.clone()));
        let _rrc = self_rc._root.get_value().borrow().upgrade();
        let _prc = self_rc._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        *self_rc.message_id_raw.borrow_mut() = _io.read_bytes(4 as usize)?.into();
        let message_id_raw = self_rc.message_id_raw.borrow();
        let _t_message_id_raw_io = BytesReader::from(message_id_raw.clone());
        let t = Self::read_into::<BytesReader, SomeIp_Header_MessageId>(&_t_message_id_raw_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
        *self_rc.message_id.borrow_mut() = t;
        *self_rc.length.borrow_mut() = _io.read_u4be()?.into();
        *self_rc.request_id_raw.borrow_mut() = _io.read_bytes(4 as usize)?.into();
        let request_id_raw = self_rc.request_id_raw.borrow();
        let _t_request_id_raw_io = BytesReader::from(request_id_raw.clone());
        let t = Self::read_into::<BytesReader, SomeIp_Header_RequestId>(&_t_request_id_raw_io, Some(self_rc._root.clone()), Some(self_rc._self.clone()))?.into();
        *self_rc.request_id.borrow_mut() = t;
        *self_rc.protocol_version.borrow_mut() = _io.read_u1()?.into();
        *self_rc.interface_version.borrow_mut() = _io.read_u1()?.into();
        *self_rc.message_type.borrow_mut() = (_io.read_u1()? as i64).try_into()?;
        *self_rc.return_code.borrow_mut() = (_io.read_u1()? as i64).try_into()?;
        Ok(())
    }
}
impl SomeIp_Header {

    /**
     * auxillary value
     * \sa AUTOSAR_PRS_SOMEIPServiceDiscoveryProtocol.pdf - section 4.1.2.1 General Requirements
     */
    pub fn is_valid_service_discovery(
        &self
    ) -> KResult<Ref<'_, bool>> {
        let _io = self._io.borrow();
        let _rrc = self._root.get_value().borrow().upgrade();
        let _prc = self._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        if self.f_is_valid_service_discovery.get() {
            return Ok(self.is_valid_service_discovery.borrow());
        }
        self.f_is_valid_service_discovery.set(true);
        *self.is_valid_service_discovery.borrow_mut() = ( ((((*self.message_id().value()? as i32) == (4294934784 as i32))) && (((*self.protocol_version() as u8) == (1 as u8))) && (((*self.interface_version() as u8) == (1 as u8))) && (*self.message_type() == SomeIp_Header_MessageTypeEnum::Notification) && (*self.return_code() == SomeIp_Header_ReturnCodeEnum::Ok)) ) as bool;
        Ok(self.is_valid_service_discovery.borrow())
    }
}

/**
 * The Message ID shall be a 32 Bit identifier that is used to identify
 * the RPC call to a method of an application or to identify an event.
 */
impl SomeIp_Header {
    pub fn message_id(&self) -> Ref<'_, OptRc<SomeIp_Header_MessageId>> {
        self.message_id.borrow()
    }
}

/**
 * [PRS_SOMEIP_00042] Length field shall contain the length in Byte
 * starting from Request ID/Client ID until the end of the SOME/IP message.
 */
impl SomeIp_Header {
    pub fn length(&self) -> Ref<'_, u32> {
        self.length.borrow()
    }
}

/**
 * The Request ID allows a provider and subscriber to differentiate
 * multiple parallel uses of the same method, event, getter or setter.
 */
impl SomeIp_Header {
    pub fn request_id(&self) -> Ref<'_, OptRc<SomeIp_Header_RequestId>> {
        self.request_id.borrow()
    }
}

/**
 * The Protocol Version identifies the used SOME/IP Header format
 * (not including the Payload format).
 */
impl SomeIp_Header {
    pub fn protocol_version(&self) -> Ref<'_, u8> {
        self.protocol_version.borrow()
    }
}

/**
 * Interface Version shall be an 8 Bit field that contains the
 * MajorVersion of the Service Interface.
 */
impl SomeIp_Header {
    pub fn interface_version(&self) -> Ref<'_, u8> {
        self.interface_version.borrow()
    }
}

/**
 * The Message Type field is used to differentiate different types of
 * messages.
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf - Table 4.4
 */
impl SomeIp_Header {
    pub fn message_type(&self) -> Ref<'_, SomeIp_Header_MessageTypeEnum> {
        self.message_type.borrow()
    }
}

/**
 * The Return Code shall be used to signal whether a request was
 * successfully processed.
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf - Table 4.5
 */
impl SomeIp_Header {
    pub fn return_code(&self) -> Ref<'_, SomeIp_Header_ReturnCodeEnum> {
        self.return_code.borrow()
    }
}
impl SomeIp_Header {
    pub fn _io(&self) -> Ref<'_, BytesReader> {
        self._io.borrow()
    }
}
impl SomeIp_Header {
    pub fn message_id_raw(&self) -> Ref<'_, Vec<u8>> {
        self.message_id_raw.borrow()
    }
}
impl SomeIp_Header {
    pub fn request_id_raw(&self) -> Ref<'_, Vec<u8>> {
        self.request_id_raw.borrow()
    }
}
#[derive(Debug, PartialEq, Clone)]
pub enum SomeIp_Header_MessageTypeEnum {
    Request,
    RequestNoReturn,
    Notification,
    RequestAck,
    RequestNoReturnAck,
    NotificationAck,
    Response,
    Error,
    ResponseAck,
    ErrorAck,
    Unknown(i64),
}

impl TryFrom<i64> for SomeIp_Header_MessageTypeEnum {
    type Error = KError;
    fn try_from(flag: i64) -> KResult<SomeIp_Header_MessageTypeEnum> {
        match flag {
            0 => Ok(SomeIp_Header_MessageTypeEnum::Request),
            1 => Ok(SomeIp_Header_MessageTypeEnum::RequestNoReturn),
            2 => Ok(SomeIp_Header_MessageTypeEnum::Notification),
            64 => Ok(SomeIp_Header_MessageTypeEnum::RequestAck),
            65 => Ok(SomeIp_Header_MessageTypeEnum::RequestNoReturnAck),
            66 => Ok(SomeIp_Header_MessageTypeEnum::NotificationAck),
            128 => Ok(SomeIp_Header_MessageTypeEnum::Response),
            129 => Ok(SomeIp_Header_MessageTypeEnum::Error),
            192 => Ok(SomeIp_Header_MessageTypeEnum::ResponseAck),
            193 => Ok(SomeIp_Header_MessageTypeEnum::ErrorAck),
            _ => Ok(SomeIp_Header_MessageTypeEnum::Unknown(flag)),
        }
    }
}

impl From<&SomeIp_Header_MessageTypeEnum> for i64 {
    fn from(v: &SomeIp_Header_MessageTypeEnum) -> Self {
        match *v {
            SomeIp_Header_MessageTypeEnum::Request => 0,
            SomeIp_Header_MessageTypeEnum::RequestNoReturn => 1,
            SomeIp_Header_MessageTypeEnum::Notification => 2,
            SomeIp_Header_MessageTypeEnum::RequestAck => 64,
            SomeIp_Header_MessageTypeEnum::RequestNoReturnAck => 65,
            SomeIp_Header_MessageTypeEnum::NotificationAck => 66,
            SomeIp_Header_MessageTypeEnum::Response => 128,
            SomeIp_Header_MessageTypeEnum::Error => 129,
            SomeIp_Header_MessageTypeEnum::ResponseAck => 192,
            SomeIp_Header_MessageTypeEnum::ErrorAck => 193,
            SomeIp_Header_MessageTypeEnum::Unknown(v) => v
        }
    }
}

impl Default for SomeIp_Header_MessageTypeEnum {
    fn default() -> Self { SomeIp_Header_MessageTypeEnum::Unknown(0) }
}

#[derive(Debug, PartialEq, Clone)]
pub enum SomeIp_Header_ReturnCodeEnum {
    Ok,
    NotOk,
    UnknownService,
    UnknownMethod,
    NotReady,
    NotReachable,
    TimeOut,
    WrongProtocolVersion,
    WrongInterfaceVersion,
    MalformedMessage,
    WrongMessageType,
    Unknown(i64),
}

impl TryFrom<i64> for SomeIp_Header_ReturnCodeEnum {
    type Error = KError;
    fn try_from(flag: i64) -> KResult<SomeIp_Header_ReturnCodeEnum> {
        match flag {
            0 => Ok(SomeIp_Header_ReturnCodeEnum::Ok),
            1 => Ok(SomeIp_Header_ReturnCodeEnum::NotOk),
            2 => Ok(SomeIp_Header_ReturnCodeEnum::UnknownService),
            3 => Ok(SomeIp_Header_ReturnCodeEnum::UnknownMethod),
            4 => Ok(SomeIp_Header_ReturnCodeEnum::NotReady),
            5 => Ok(SomeIp_Header_ReturnCodeEnum::NotReachable),
            6 => Ok(SomeIp_Header_ReturnCodeEnum::TimeOut),
            7 => Ok(SomeIp_Header_ReturnCodeEnum::WrongProtocolVersion),
            8 => Ok(SomeIp_Header_ReturnCodeEnum::WrongInterfaceVersion),
            9 => Ok(SomeIp_Header_ReturnCodeEnum::MalformedMessage),
            10 => Ok(SomeIp_Header_ReturnCodeEnum::WrongMessageType),
            _ => Ok(SomeIp_Header_ReturnCodeEnum::Unknown(flag)),
        }
    }
}

impl From<&SomeIp_Header_ReturnCodeEnum> for i64 {
    fn from(v: &SomeIp_Header_ReturnCodeEnum) -> Self {
        match *v {
            SomeIp_Header_ReturnCodeEnum::Ok => 0,
            SomeIp_Header_ReturnCodeEnum::NotOk => 1,
            SomeIp_Header_ReturnCodeEnum::UnknownService => 2,
            SomeIp_Header_ReturnCodeEnum::UnknownMethod => 3,
            SomeIp_Header_ReturnCodeEnum::NotReady => 4,
            SomeIp_Header_ReturnCodeEnum::NotReachable => 5,
            SomeIp_Header_ReturnCodeEnum::TimeOut => 6,
            SomeIp_Header_ReturnCodeEnum::WrongProtocolVersion => 7,
            SomeIp_Header_ReturnCodeEnum::WrongInterfaceVersion => 8,
            SomeIp_Header_ReturnCodeEnum::MalformedMessage => 9,
            SomeIp_Header_ReturnCodeEnum::WrongMessageType => 10,
            SomeIp_Header_ReturnCodeEnum::Unknown(v) => v
        }
    }
}

impl Default for SomeIp_Header_ReturnCodeEnum {
    fn default() -> Self { SomeIp_Header_ReturnCodeEnum::Unknown(0) }
}


/**
 * [PRS_SOMEIP_00035] The assignment of the Message ID shall be up to
 * the user. However, the Message ID shall be unique for the whole
 * system (i.e. the vehicle). TheMessage ID is similar to a CAN ID and
 * should be handled via a comparable process.
 * [PRS_SOMEIP_00038] Message IDs of method calls shall be structured in
 * the ID with 2^16 services with 2^15 methods.
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf 4.1.1.1  Message ID
 */

#[derive(Default, Debug, Clone)]
pub struct SomeIp_Header_MessageId {
    pub _root: SharedType<SomeIp>,
    pub _parent: SharedType<SomeIp_Header>,
    pub _self: SharedType<Self>,
    service_id: RefCell<u16>,
    sub_id: RefCell<bool>,
    method_id: RefCell<u64>,
    event_id: RefCell<u64>,
    _io: RefCell<BytesReader>,
    f_value: Cell<bool>,
    value: RefCell<u32>,
}
impl KStruct for SomeIp_Header_MessageId {
    type Root = SomeIp;
    type Parent = SomeIp_Header;

    fn read<S: KStream>(
        self_rc: &OptRc<Self>,
        _io: &S,
        _root: SharedType<Self::Root>,
        _parent: SharedType<Self::Parent>,
    ) -> KResult<()> {
        *self_rc._io.borrow_mut() = _io.clone();
        self_rc._root.set(_root.get());
        self_rc._parent.set(_parent.get());
        self_rc._self.set(Ok(self_rc.clone()));
        let _rrc = self_rc._root.get_value().borrow().upgrade();
        let _prc = self_rc._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        *self_rc.service_id.borrow_mut() = _io.read_u2be()?.into();
        *self_rc.sub_id.borrow_mut() = _io.read_bits_int_be(1)? != 0;
        if ((*self_rc.sub_id() as bool) == (false as bool)) {
            *self_rc.method_id.borrow_mut() = _io.read_bits_int_be(15)?;
        }
        if ((*self_rc.sub_id() as bool) == (true as bool)) {
            *self_rc.event_id.borrow_mut() = _io.read_bits_int_be(15)?;
        }
        Ok(())
    }
}
impl SomeIp_Header_MessageId {

    /**
     * The value provides the undissected Message ID
     */
    pub fn value(
        &self
    ) -> KResult<Ref<'_, u32>> {
        let _io = self._io.borrow();
        let _rrc = self._root.get_value().borrow().upgrade();
        let _prc = self._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        if self.f_value.get() {
            return Ok(self.value.borrow());
        }
        self.f_value.set(true);
        let _pos = _io.pos();
        _io.seek(0 as usize)?;
        *self.value.borrow_mut() = _io.read_u4be()?.into();
        _io.seek(_pos)?;
        Ok(self.value.borrow())
    }
}

/**
 * Service ID
 */
impl SomeIp_Header_MessageId {
    pub fn service_id(&self) -> Ref<'_, u16> {
        self.service_id.borrow()
    }
}

/**
 * Single bit to flag, if there is a Method or a Event ID
 */
impl SomeIp_Header_MessageId {
    pub fn sub_id(&self) -> Ref<'_, bool> {
        self.sub_id.borrow()
    }
}

/**
 * Method ID
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf - Table 4.1.
 */
impl SomeIp_Header_MessageId {
    pub fn method_id(&self) -> Ref<'_, u64> {
        self.method_id.borrow()
    }
}

/**
 * Event ID
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf - Table 4.6
 */
impl SomeIp_Header_MessageId {
    pub fn event_id(&self) -> Ref<'_, u64> {
        self.event_id.borrow()
    }
}
impl SomeIp_Header_MessageId {
    pub fn _io(&self) -> Ref<'_, BytesReader> {
        self._io.borrow()
    }
}

/**
 * The Request ID allows a provider and subscriber to differentiate
 * multiple parallel usesof the same method, event, getter or setter.
 * \sa AUTOSAR_PRS_SOMEIPProtocol.pdf - section 4.1.1.3  Request ID
 */

#[derive(Default, Debug, Clone)]
pub struct SomeIp_Header_RequestId {
    pub _root: SharedType<SomeIp>,
    pub _parent: SharedType<SomeIp_Header>,
    pub _self: SharedType<Self>,
    client_id: RefCell<u16>,
    session_id: RefCell<u16>,
    _io: RefCell<BytesReader>,
    f_value: Cell<bool>,
    value: RefCell<u32>,
}
impl KStruct for SomeIp_Header_RequestId {
    type Root = SomeIp;
    type Parent = SomeIp_Header;

    fn read<S: KStream>(
        self_rc: &OptRc<Self>,
        _io: &S,
        _root: SharedType<Self::Root>,
        _parent: SharedType<Self::Parent>,
    ) -> KResult<()> {
        *self_rc._io.borrow_mut() = _io.clone();
        self_rc._root.set(_root.get());
        self_rc._parent.set(_parent.get());
        self_rc._self.set(Ok(self_rc.clone()));
        let _rrc = self_rc._root.get_value().borrow().upgrade();
        let _prc = self_rc._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        *self_rc.client_id.borrow_mut() = _io.read_u2be()?.into();
        *self_rc.session_id.borrow_mut() = _io.read_u2be()?.into();
        Ok(())
    }
}
impl SomeIp_Header_RequestId {

    /**
     * The value provides the undissected Request ID
     */
    pub fn value(
        &self
    ) -> KResult<Ref<'_, u32>> {
        let _io = self._io.borrow();
        let _rrc = self._root.get_value().borrow().upgrade();
        let _prc = self._parent.get_value().borrow().upgrade();
        let _r = _rrc.as_ref().unwrap();
        if self.f_value.get() {
            return Ok(self.value.borrow());
        }
        self.f_value.set(true);
        let _pos = _io.pos();
        _io.seek(0 as usize)?;
        *self.value.borrow_mut() = _io.read_u4be()?.into();
        _io.seek(_pos)?;
        Ok(self.value.borrow())
    }
}
impl SomeIp_Header_RequestId {
    pub fn client_id(&self) -> Ref<'_, u16> {
        self.client_id.borrow()
    }
}
impl SomeIp_Header_RequestId {
    pub fn session_id(&self) -> Ref<'_, u16> {
        self.session_id.borrow()
    }
}
impl SomeIp_Header_RequestId {
    pub fn _io(&self) -> Ref<'_, BytesReader> {
        self._io.borrow()
    }
}