### DeliverSm Usage Example Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/owned/deliver_sm.rs.html Example demonstrating how to build a DeliverSm PDU with various fields. ```APIDOC ## DeliverSm Construction Example ### Description This example shows how to create a `DeliverSm` PDU using the builder pattern, setting common fields and TLVs. ### Code ```rust use crate::types::owned::{AnyOctetString, OctetString}; use crate::smpp::registered_delivery::RegisteredDelivery; use crate::smpp::replace_if_present_flag::ReplaceIfPresentFlag; use crate::smpp::ton::Ton; use crate::smpp::npi::Npi; use crate::smpp::data_coding::DataCoding; use crate::smpp::tlv::MessageDeliveryRequestTlvValue; use crate::smpp::tlv::message_payload::MessagePayload; use crate::smpp::tlv::callback_num_pres_ind::{CallbackNumPresInd, Presentation, Screening}; use crate::smpp::coctet_string::COctetString; use crate::smpp::empty_or_full_coctet_string::EmptyOrFullCOctetString; // Assuming DeliverSm and its builder are in scope // use rusmpp_core::pdus::owned::deliver_sm::DeliverSm; let short_message_content = OctetString::from_static_slice(b"Short Message").unwrap(); let deliver_sm_pdu = DeliverSm::builder() .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::from_str("Source Address").unwrap()) .dest_addr_ton(Ton::International) .dest_addr_npi(Npi::Isdn) .destination_addr(COctetString::from_str("Destination Address").unwrap()) .schedule_delivery_time(EmptyOrFullCOctetString::empty()) .validity_period(EmptyOrFullCOctetString::empty()) .registered_delivery(RegisteredDelivery::default()) .replace_if_present_flag(ReplaceIfPresentFlag::Replace) .protocol_id(0) .data_coding(DataCoding::default()) .sm_default_msg_id(0) .short_message(short_message_content.clone()) .tlvs(alloc::vec![ MessageDeliveryRequestTlvValue::MessagePayload(MessagePayload::new( AnyOctetString::from_static_slice(b"Message Payload"), )), MessageDeliveryRequestTlvValue::CallbackNumPresInd( CallbackNumPresInd::new( Presentation::NumberNotAvailable, Screening::VerifiedAndPassed, ), ), ]) .build(); // You can then use deliver_sm_pdu for sending or further processing. // For example, asserting its properties: // assert_eq!(deliver_sm_pdu.short_message(), &short_message_content); // assert_eq!(deliver_sm_pdu.sm_length(), short_message_content.length() as u8); ``` ``` -------------------------------- ### Trim ASCII Start Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html Example showing how `trim_ascii_start` removes leading ASCII whitespace from a byte slice. ```rust assert_eq!(b" \t hello world\n".trim_ascii_start(), b"hello world\n"); assert_eq!(b" ".trim_ascii_start(), b""); assert_eq!(b"" .trim_ascii_start(), b""); ``` -------------------------------- ### Slice Length Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html A basic example illustrating how to get the length of a slice. ```rust let a = [1, 2, 3]; assert_eq!(a.len(), 3); ``` -------------------------------- ### SubmitMulti Builder Example Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/submit_multi.rs.html Demonstrates building a SubmitMulti PDU with various parameters set. This example showcases how to chain builder methods to configure the PDU before building it. ```rust Self::builder() .service_type(ServiceType::default()) .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::new(b"Source Address\0").unwrap()) .esm_class(EsmClass::default()) .protocol_id(0) .priority_flag(PriorityFlag::default()) .schedule_delivery_time(EmptyOrFullCOctetString::empty()) .validity_period(EmptyOrFullCOctetString::empty()) .registered_delivery(RegisteredDelivery::default()) .replace_if_present_flag(ReplaceIfPresentFlag::default()) .data_coding(DataCoding::default()) .sm_default_msg_id(0) .short_message(OctetString::new(b"Short Message").unwrap()) .build() ``` -------------------------------- ### ReplaceSm Builder Example Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/owned/replace_sm.rs.html An example demonstrating how to build a ReplaceSm PDU with specific parameters. This includes setting the message ID, sender address details, delivery times, and message content. ```rust Self::builder() .message_id(COctetString::from_str("123456789012345678901234").unwrap()) .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::from_str("Source Addr").unwrap()) .schedule_delivery_time( EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap(), ) .validity_period( EmptyOrFullCOctetString::from_static_slice(b"2023-10-01T12:00\0").unwrap() ) .registered_delivery(RegisteredDelivery::default()) .sm_default_msg_id(0) .short_message(OctetString::from_static_slice(b"Short Message").unwrap()) .build() ``` -------------------------------- ### Decoding SMPP PDU Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/command/owned/struct.Command.html Illustrates how an SMPP PDU is decoded, showing the header fields and their corresponding values. This example is for a bind_transmitter PDU. ```text Sample PDU (Values are shown in Hex format): 00 00 00 2F 00 00 00 02 00 00 00 00 00 00 00 01 53 4D 50 50 33 54 45 53 54 00 73 65 63 72 65 74 30 38 00 53 55 42 4D 49 54 31 00 50 01 01 00 The 16-octet header would be decoded as follows: Octets| Description ---|--- 00 00 00 2F| Command Length (47) 00 00 00 02| Command ID (bind_transmitter) 00 00 00 00| Command Status (0) 00 00 00 01| Sequence Number (1) The remaining data represents the PDU body (which in this example relates to the bind_transmitter PDU). This is diagnosed as follows: Octets| Value ---|--- 53 4D 50 50 33 54 45 53 54 00| system_id (“SMPP3TEST”) 73 65 63 72 65 74 30 38 00| password (“secret08”) 53 55 42 4D 49 54 31 00| system_type (“SUBMIT1”) 50| interface_version (0x50 “V5.0 compliant”) 01| addr_ton (0x01) 01| addr_npi (0x01) 00| addr_range (NULL) ``` -------------------------------- ### SubmitSm Builder Example 2 - rusmpp-core Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/submit_sm.rs.html Another example of building a SubmitSm PDU, showcasing different options for ESM class, priority, and replacement flags. ```rust Self::builder() .service_type(ServiceType::new( GenericServiceType::CellularMessaging.into(), )) .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::new(b"Source Address\0").unwrap()) .dest_addr_ton(Ton::International) .dest_addr_npi(Npi::Isdn) .destination_addr(COctetString::new(b"Destination Address\0").unwrap()) .esm_class(EsmClass::new( MessagingMode::Default, MessageType::ShortMessageContainsIntermediateDeliveryNotification, Ansi41Specific::ShortMessageContainsUserAcknowledgment, GsmFeatures::SetUdhiAndReplyPath, )) .protocol_id(0) .priority_flag(PriorityFlag::from(PriorityFlagType::from( Ansi136::VeryUrgent, ))) .schedule_delivery_time( EmptyOrFullCOctetString::new(b"2023-09-01T12:01\0").unwrap(), ) .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:20\0").unwrap()) .registered_delivery(RegisteredDelivery::request_all()) .replace_if_present_flag(ReplaceIfPresentFlag::DoNotReplace) .data_coding(DataCoding::Jis) .sm_default_msg_id(96) .short_message(OctetString::new(b"Short Message").unwrap()) .tlvs( ``` -------------------------------- ### Example Implementation of DecodeWithKeyOptional for Foo Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/decode/owned/trait.DecodeWithKeyOptional.html An example demonstrating how to implement the DecodeWithKeyOptional trait for a custom enum `Foo`, showing different decoding logic based on the provided key. ```APIDOC ## Example Implementation: Foo ```rust #[derive(Debug, PartialEq, Eq)] enum Foo { A, B(u16), C(AnyOctetString), } impl DecodeWithKeyOptional for Foo { type Key = u32; fn decode( key: Self::Key, src: &mut BytesMut, length: usize, ) -> Result, DecodeError> { if length == 0 { match key { 0x00000000 => return Ok(Some((Foo::A, 0))), _ => return Ok(None), } } match key { 0x01020304 => { let (a, size) = Decode::decode(src)?; Ok(Some((Foo::B(a), size))) } 0x04030201 => { let (b, size) = AnyOctetString::decode(src, length)?; Ok(Some((Foo::C(b), size))) } _ => Err(DecodeError::unsupported_key(key)), } } } ``` ### Usage Examples #### Decoding Foo::A ```rust // Received over the wire let length = 4; // Key is A let mut buf = BytesMut::from(&[ 0x00, 0x00, 0x00, 0x00, // Key 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ][..]); let index = 0; let (key, size) = Decode::decode(&mut buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &mut buf, length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::A; assert_eq!(size, 0); assert_eq!(foo, expected); assert_eq!(&buf[..], &[0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding None for Foo::B ```rust // Received over the wire let length = 4; // Key is B, but the received length indicates no value let mut buf = BytesMut::from(&[ 0x01, 0x02, 0x03, 0x04, // Key 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ][..]); let index = 0; let (key, size) = Decode::decode(&mut buf).unwrap(); let index = index + size; let value = Foo::decode(key, &mut buf, length - index).unwrap(); assert!(value.is_none()); assert_eq!(&buf[..], &[0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding Foo::B ```rust // Received over the wire let length = 8; // Key is B let mut buf = BytesMut::from(&[ 0x01, 0x02, 0x03, 0x04, // Key 0x05, 0x06, // Value 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ][..]); let index = 0; let (key, size) = Decode::decode(&mut buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &mut buf, length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::B(0x0506); assert_eq!(size, 2); assert_eq!(foo, expected); assert_eq!(&buf[..], &[0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding Foo::C ```rust // Received over the wire let length = 8; // Key is C let mut buf = BytesMut::from(&[ 0x04, 0x03, 0x02, 0x01, // Key 0x05, 0x06, 0x07, 0x08, // Value 0x09, 0x0A, 0x0B, // Rest ][..]); let index = 0; let (key, size) = Decode::decode(&mut buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &mut buf, length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::C(AnyOctetString::from_static_slice(&[0x05, 0x06, 0x07, 0x08])); assert_eq!(size, 4); assert_eq!(foo, expected); assert_eq!(&buf[..], &[0x09, 0x0A, 0x0B]); ``` ``` -------------------------------- ### Example Implementation of DecodeWithKeyOptional for Foo Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/decode/borrowed/trait.DecodeWithKeyOptional.html This example demonstrates how to implement the `DecodeWithKeyOptional` trait for a custom enum `Foo`. It shows how different keys map to different variants of the enum, and how to handle the decoding of associated data for each variant. ```APIDOC ## Implementation Example for Foo ```rust #[derive(Debug, PartialEq, Eq)] enum Foo<'a> { A, B(u16), C(AnyOctetString<'a>), } impl<'a> DecodeWithKeyOptional<'a> for Foo<'a> { type Key = u32; fn decode( key: Self::Key, src: &'a [u8], length: usize, ) -> Result, DecodeError> { if length == 0 { match key { 0x00000000 => return Ok(Some((Foo::A, 0))), _ => return Ok(None), } } match key { 0x01020304 => { let (a, size) = Decode::decode(src)?; Ok(Some((Foo::B(a), size))) } 0x04030201 => { let (b, size) = AnyOctetString::decode(src, length)?; Ok(Some((Foo::C(b), size))) } _ => Err(DecodeError::unsupported_key(key)), } } } ``` ### Usage Examples #### Decoding Foo::A ```rust // Received over the wire let length = 4; // Key is A let buf = [ 0x00, 0x00, 0x00, 0x00, // Key 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ]; let index = 0; let (key, size) = Decode::decode(buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &buf[index..], length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::A; assert_eq!(size, 0); assert_eq!(foo, expected); assert_eq!(&buf[index..], &[0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding None for Foo::B (Insufficient Length) ```rust // Received over the wire let length = 4; // Key is B, but the received length indicates no value let buf = [ 0x01, 0x02, 0x03, 0x04, // Key 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ]; let index = 0; let (key, size) = Decode::decode(buf).unwrap(); let index = index + size; let value = Foo::decode(key, &buf[index..], length - index).unwrap(); assert!(value.is_none()); assert_eq!(&buf[index..], &[0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding Foo::B ```rust // Received over the wire let length = 8; // Key is B let buf = [ 0x01, 0x02, 0x03, 0x04, // Key 0x05, 0x06, // Value 0x07, 0x08, 0x09, 0x0A, 0x0B, // Rest ]; let index = 0; let (key, size) = Decode::decode(buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &buf[index..], length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::B(0x0506); assert_eq!(size, 2); assert_eq!(foo, expected); assert_eq!(&buf[index..], &[0x07, 0x08, 0x09, 0x0A, 0x0B]); ``` #### Decoding Foo::C ```rust // Received over the wire let length = 8; // Key is C let buf = [ 0x04, 0x03, 0x02, 0x01, // Key 0x05, 0x06, 0x07, 0x08, // Value 0x09, 0x0A, 0x0B, // Rest ]; let index = 0; let (key, size) = Decode::decode(buf).unwrap(); let index = index + size; let (foo, size) = Foo::decode(key, &buf[index..], length - index) .unwrap() .unwrap(); let index = index + size; let expected = Foo::C(AnyOctetString::new(&[0x05, 0x06, 0x07, 0x08])); assert_eq!(size, 4); assert_eq!(foo, expected); assert_eq!(&buf[index..], &[0x09, 0x0A, 0x0B]); ``` ``` -------------------------------- ### Example Implementation of Decode for Foo Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/decode/owned/trait.Decode.html Demonstrates how to implement the `Decode` trait for a custom struct `Foo`. This example shows decoding nested values and tracking the total bytes consumed. ```rust #[derive(Debug, PartialEq, Eq)] struct Foo { a: u8, b: u16, c: u32, } impl Decode for Foo { fn decode(src: &mut BytesMut) -> Result<(Self, usize), DecodeError> { let index = 0; let (a, size) = Decode::decode(src)?; let index = index + size; let (b, size) = Decode::decode(src)?; let index = index + size; let (c, size) = Decode::decode(src)?; let index = index + size; Ok((Foo { a, b, c }, index)) } } ``` ```rust let mut buf = BytesMut::from(&[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08][..]); let expected = Foo { a: 0x01, b: 0x0203, c: 0x04050607, }; let (foo, size) = Foo::decode(&mut buf).unwrap(); assert_eq!(size, 7); assert_eq!(foo, expected); assert_eq!(&buf[..], &[0x08]); ``` -------------------------------- ### Example Implementation of Decode for Foo Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/decode/borrowed/trait.Decode.html This example demonstrates how to implement the `Decode` trait for a custom struct `Foo`. The `decode` method sequentially decodes its fields from the byte slice, accumulating the size. ```APIDOC ## Example Implementation ```rust #[derive(Debug, PartialEq, Eq)] struct Foo { a: u8, b: u16, c: u32, } impl<'a> Decode<'a> for Foo { fn decode(src: &'a [u8]) -> Result<(Self, usize), DecodeError> { let mut index = 0; let (a, size) = Decode::decode(&src[index..])?; index += size; let (b, size) = Decode::decode(&src[index..])?; index += size; let (c, size) = Decode::decode(&src[index..])?; index += size; Ok((Foo { a, b, c }, index)) } } let buf = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; let expected = Foo { a: 0x01, b: 0x0203, c: 0x04050607, }; let (foo, size) = Foo::decode(buf).unwrap(); assert_eq!(size, 7); assert_eq!(foo, expected); assert_eq!(&buf[size..], &[0x08]); ``` ``` -------------------------------- ### Trim ASCII Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html Example demonstrating `trim_ascii` which removes both leading and trailing ASCII whitespace from a byte slice. ```rust assert_eq!(b"\r hello world\n ".trim_ascii(), b"hello world"); assert_eq!(b" ".trim_ascii(), b""); assert_eq!(b"" .trim_ascii(), b""); ``` -------------------------------- ### COctetString Examples Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.COctetString.html Illustrates the encoding of 'Hello', decimal, hexadecimal, and empty strings as COctetString. ```text The string “Hello” would be encoded in 6 octets (5 characters of “Hello” and NULL octet) as follows: 0x48656C6C6F00 ``` ```text A Decimal `COctetString` “123456789” would be encoded as follows: 0x31323334353637383900 ``` ```text A Hexadecimal `COctetString` “A2F5ED278FC” would be encoded as follows: 0x413246354544323738464300 ``` ```text A NULL string “” is encoded as 0x00 ``` -------------------------------- ### Get First Slice Element Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html Example of using `first` to safely get the first element of a slice, returning None if the slice is empty. ```rust let v = [10, 40, 30]; assert_eq!(Some(&10), v.first()); let w: &[i32] = &[]; assert_eq!(None, w.first()); ``` -------------------------------- ### SubmitSm Construction and Basic Methods Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/pdus/owned/struct.SubmitSm.html Demonstrates how to construct a SubmitSm PDU using its `new` function and provides examples of common methods for accessing and modifying its fields. ```APIDOC ## `SubmitSm::new` ### Description Constructs a new `SubmitSm` PDU with the provided parameters. ### Parameters - `service_type`: `ServiceType` - The service type for the message. - `source_addr_ton`: `Ton` - The Ton (Type of Number) for the source address. - `source_addr_npi`: `Npi` - The NPI (Numbering Plan Identification) for the source address. - `source_addr`: `COctetString<1, 21>` - The source address of the message. - `dest_addr_ton`: `Ton` - The Ton for the destination address. - `dest_addr_npi`: `Npi` - The NPI for the destination address. - `destination_addr`: `COctetString<1, 21>` - The destination address of the message. - `esm_class`: `EsmClass` - The ESM class field. - `protocol_id`: `u8` - The protocol ID. - `priority_flag`: `PriorityFlag` - The priority flag. - `schedule_delivery_time`: `EmptyOrFullCOctetString<17>` - The scheduled delivery time. - `validity_period`: `EmptyOrFullCOctetString<17>` - The validity period. - `registered_delivery`: `RegisteredDelivery` - The registered delivery flag. - `replace_if_present_flag`: `ReplaceIfPresentFlag` - The replace if present flag. - `data_coding`: `DataCoding` - The data coding scheme. - `sm_default_msg_id`: `u8` - The default message ID. - `short_message`: `OctetString<0, 255>` - The short message content. - `tlvs`: `Vec` - A vector of TLVs (Tag-Length-Value) for additional parameters. ### Returns - `Self` - A new `SubmitSm` instance. ## `SubmitSm::sm_length` ### Description Returns the length of the short message. ### Returns - `u8` - The length of the short message. ## `SubmitSm::short_message` ### Description Returns a reference to the short message content. ### Returns - `&OctetString<0, 255>` - A reference to the short message. ## `SubmitSm::set_short_message` ### Description Sets the `short_message` and updates the `sm_length`. ### Note `short_message` is superceded by `TlvValue::MessagePayload` and should only be used if `TlvValue::MessagePayload` is not present. ### Parameters - `short_message`: `OctetString<0, 255>` - The short message content to set. ## `SubmitSm::tlvs` ### Description Returns a slice of the TLVs associated with the PDU. ### Returns - `&[Tlv]` - A slice of TLVs. ## `SubmitSm::set_tlvs` ### Description Sets the TLVs for the PDU. ### Parameters - `tlvs`: `Vec` - The vector of TLVs to set. ## `SubmitSm::clear_tlvs` ### Description Clears all TLVs from the PDU. ## `SubmitSm::push_tlv` ### Description Adds a TLV to the PDU. ### Parameters - `tlv`: `impl Into` - The TLV to add. ## `SubmitSm::builder` ### Description Returns a `SubmitSmBuilder` to facilitate the construction of a `SubmitSm` PDU. ### Returns - `SubmitSmBuilder` - The builder instance. ## `SubmitSm::with_data_coding` ### Description Sets the `data_coding` field of the `SubmitSm` PDU. ### Parameters - `data_coding`: `DataCoding` - The data coding to set. ### Returns - `Self` - The modified `SubmitSm` instance. ## `SubmitSm::with_udhi_indicator` ### Description Sets the UDH Indicator bit in the GSM Features field of the `esm_class`. ### Returns - `Self` - The modified `SubmitSm` instance. ## `SubmitSm::with_short_message` ### Description Sets the `short_message` and `sm_length` fields. ### Note See `Self::set_short_message` for details. ### Parameters - `short_message`: `OctetString<0, 255>` - The short message content to set. ### Returns - `Self` - The modified `SubmitSm` instance. ``` -------------------------------- ### Split First Slice Element Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html Example of using `split_first` to get the first element and the rest of the slice. Returns None for an empty slice. ```rust let x = &[0, 1, 2]; if let Some((first, elements)) = x.split_first() { assert_eq!(first, &0); assert_eq!(elements, &[1, 2]); } ``` -------------------------------- ### SubmitSm Builder Example 1 - rusmpp-core Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/submit_sm.rs.html Demonstrates building a SubmitSm PDU with various parameters set. This includes service type, addresses, message class, and delivery options. ```rust Self::builder() .service_type(ServiceType::new( GenericServiceType::CellularMessaging.into(), )) .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::new(b"Source Address\0").unwrap()) .dest_addr_ton(Ton::International) .dest_addr_npi(Npi::Isdn) .destination_addr(COctetString::new(b"Destination Address\0").unwrap()) .esm_class(EsmClass::new( MessagingMode::StoreAndForward, MessageType::ShortMessageContainsMCDeliveryReceipt, Ansi41Specific::ShortMessageContainsDeliveryAcknowledgement, GsmFeatures::SetUdhiAndReplyPath, )) .protocol_id(0) .priority_flag(PriorityFlag::from(PriorityFlagType::from(Ansi136::Bulk))) .schedule_delivery_time( EmptyOrFullCOctetString::new(b"2023-09-01T12:00\0").unwrap(), ) .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap()) .registered_delivery(RegisteredDelivery::request_all()) .replace_if_present_flag(ReplaceIfPresentFlag::Replace) .data_coding(DataCoding::Ksc5601) .sm_default_msg_id(69) .short_message(OctetString::new(b"Short Message").unwrap()) .build() ``` -------------------------------- ### Get Command Builder Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/command/borrowed/struct.Command.html Returns a builder for constructing Command instances, starting with the status. ```rust pub fn builder() -> CommandStatusBuilder<'a, N> ``` -------------------------------- ### Example ReplaceSm PDU Construction Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/replace_sm.rs.html Demonstrates the construction of a `ReplaceSm` PDU using its builder, setting various fields including message ID, sender details, and message content. ```rust Self::builder() .message_id(COctetString::new(b"123456789012345678901234\0").unwrap()) .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::new(b"Source Addr\0").unwrap()) .schedule_delivery_time( EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap(), ) .validity_period(EmptyOrFullCOctetString::new(b"2023-10-01T12:00\0").unwrap()) .registered_delivery(RegisteredDelivery::default()) .sm_default_msg_id(0) .short_message(OctetString::new(b"Short Message").unwrap()) .build() ``` -------------------------------- ### Iterating over a slice Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.AnyOctetString.html Use `iter()` to get an iterator that yields all items from start to end of the slice. This is useful for processing each element sequentially. ```rust let x = &[1, 2, 4]; let mut iterator = x.iter(); assert_eq!(iterator.next(), Some(&1)); assert_eq!(iterator.next(), Some(&2)); assert_eq!(iterator.next(), Some(&4)); assert_eq!(iterator.next(), None); ``` -------------------------------- ### SubmitMulti Default and Builder Initialization Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/owned/submit_multi.rs.html Demonstrates initializing a SubmitMulti PDU with default values and using the builder pattern to set destination addresses. Verifies the initial state and the state after setting addresses. ```rust fn count() { let submit_multi = SubmitMulti::default(); assert_eq!(submit_multi.number_of_dests(), 0); assert!(submit_multi.dest_address().is_empty()); let submit_sm = SubmitMulti::builder() .dest_address(alloc::vec![ DestAddress::SmeAddress(SmeAddress::new( Ton::International, Npi::Isdn, COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), )), DestAddress::DistributionListName(DistributionListName::new( COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), )), ]) .build(); assert_eq!(submit_sm.number_of_dests(), 2); assert_eq!(submit_sm.dest_address().len(), 2); let submit_sm = SubmitMulti::builder() .push_dest_address(DestAddress::SmeAddress(SmeAddress::new( Ton::International, Npi::Isdn, COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), ))) .push_dest_address(DestAddress::DistributionListName( DistributionListName::new( COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), ), )) .build(); assert_eq!(submit_sm.number_of_dests(), 2); assert_eq!(submit_sm.dest_address().len(), 2); let submit_sm = SubmitMulti::builder() .push_dest_address(DestAddress::SmeAddress(SmeAddress::new( Ton::International, Npi::Isdn, COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), ))) .push_dest_address(DestAddress::DistributionListName( DistributionListName::new( COctetString::from_static_slice(b"1234567890123456789\0").unwrap(), ), )) .clear_dest_address() .build(); assert_eq!(submit_sm.number_of_dests(), 0); assert!(submit_sm.dest_address().is_empty()); } } ``` -------------------------------- ### Get element offset in slice Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.AnyOctetString.html Finds the index of an element reference within a slice using pointer arithmetic. Returns None if the element is not aligned with the start of an element in the slice. This is a nightly-only experimental API. ```rust #![feature(substr_range)] let nums: &[u32] = &[1, 7, 1, 1]; let num = &nums[2]; assert_eq!(num, &1); assert_eq!(nums.element_offset(num), Some(2)); ``` ```rust #![feature(substr_range)] let arr: &[[u32; 2]] = &[[0, 1], [2, 3]]; let flat_arr: &[u32] = arr.as_flattened(); let ok_elm: &[u32; 2] = flat_arr[0..2].try_into().unwrap(); let weird_elm: &[u32; 2] = flat_arr[1..3].try_into().unwrap(); assert_eq!(ok_elm, &[0, 1]); assert_eq!(weird_elm, &[1, 2]); assert_eq!(arr.element_offset(ok_elm), Some(0)); // Points to element 0 assert_eq!(arr.element_offset(weird_elm), None); // Points between element 0 and 1 ``` -------------------------------- ### SubmitMulti with TLV Example Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/submit_multi.rs.html Shows how to build a SubmitMulti PDU and add a TLV (Tag-Length-Value) element, specifically a MessagePayload. The `push_tlv` method returns a Result, which must be handled. ```rust Self::builder() .short_message(OctetString::new(b"Short Message").unwrap()) .push_tlv(MessageSubmissionRequestTlvValue::MessagePayload( MessagePayload::new(AnyOctetString::new(b"Message Payload")), )) .unwrap() .build() ``` -------------------------------- ### get Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.AnyOctetString.html Safely gets an element or subslice by index. Returns None if the index is out of bounds. ```APIDOC ## pub fn get(&self, index: I) -> Option<&>::Output> ### Description Returns a reference to an element or subslice depending on the type of index. * If given a position, returns a reference to the element at that position or `None` if out of bounds. * If given a range, returns the subslice corresponding to that range, or `None` if out of bounds. ### Parameters * `index`: `I` where `I: SliceIndex<[T]>` - The index or range to access. ### Returns * `Option<&>::Output>`: An `Option` containing a reference to the element or subslice, or `None` if the index is out of bounds. ### Examples ```rust let v = [10, 40, 30]; assert_eq!(Some(&40), v.get(1)); assert_eq!(Some(&[10, 40][..]), v.get(0..2)); assert_eq!(None, v.get(3)); assert_eq!(None, v.get(0..4)); ``` ``` -------------------------------- ### Example Usage of Encode Trait Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/encode/trait.Encode.html This example demonstrates how to use the `Encode` trait with a custom struct `Foo`. It shows the implementation of `Length` and `Encode` for `Foo`, and then provides a usage example where a `Foo` instance is encoded into a byte buffer. ```APIDOC ```rust struct Foo { a: u8, b: u16, c: u32, } impl Length for Foo { fn length(&self) -> usize { self.a.length() + self.b.length() + self.c.length() } } impl Encode for Foo { fn encode(&self, dst: &mut [u8]) -> usize { let mut size = 0; size += self.a.encode(&mut dst[size..]); size += self.b.encode(&mut dst[size..]); size += self.c.encode(&mut dst[size..]); size } } let foo = Foo { a: 0x01, b: 0x0203, c: 0x04050607, }; let buf = &mut [0u8; 1024]; assert!(buf.len() >= foo.length()); let size = foo.encode(buf); let expected = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]; assert_eq!(size, 7); assert_eq!(&buf[..size], expected); ``` ``` -------------------------------- ### Escape ASCII Example Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/types/borrowed/struct.EmptyOrFullCOctetString.html Example demonstrating the usage of `escape_ascii` to convert a byte slice into an escaped string. ```rust let s = b"0\t\r\n'\"\\\x9d"; let escaped = s.escape_ascii().to_string(); assert_eq!(escaped, "0\\t\\r\\n\'\\"\\\\\\x9d"); ``` -------------------------------- ### Example Usage of DecodeWithLength Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/decode/borrowed/trait.DecodeWithLength.html An example demonstrating how the DecodeWithLength trait is implemented and used for a custom struct `Foo`. ```APIDOC ## Example Implementation ```rust // Received over the wire let length = 8; let buf = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09]; let expected = Foo { a: 0x01, b: 0x0203, c: AnyOctetString::new(&[0x04, 0x05, 0x06, 0x07, 0x08]), }; let (foo, size) = Foo::decode(buf, length).unwrap(); assert_eq!(size, 8); assert_eq!(foo, expected); assert_eq!(&buf[size..], &[0x09]); ``` ``` -------------------------------- ### Get size hint for UserMessageReference Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/values/struct.UserMessageReference.html Gets a size hint for how many bytes are needed to construct a UserMessageReference. ```rust fn size_hint(depth: usize) -> (usize, Option)> ``` -------------------------------- ### AlertNotification Builder and Instances Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/pdus/borrowed/alert_notification.rs.html Demonstrates the creation of AlertNotification PDUs using the builder pattern. Includes examples with default values, specific MS availability status, and various source/ESME address configurations. ```rust impl TestInstance for AlertNotification<'_> { fn instances() -> alloc::vec::Vec { alloc::vec![ Self::default(), Self::builder() .ms_availability_status(Some(MsAvailabilityStatus::Available)) .build(), Self::builder() .source_addr_ton(Ton::International) .source_addr_npi(Npi::Isdn) .source_addr(COctetString::new(b"1234567890\0").unwrap()) .esme_addr_ton(Ton::International) .esme_addr_npi(Npi::Isdn) .esme_addr(COctetString::new(b"0987654321\0").unwrap()) .ms_availability_status(Some(MsAvailabilityStatus::Available)) .build(), Self::builder() .source_addr_ton(Ton::NetworkSpecific) .source_addr_npi(Npi::LandMobile) .source_addr(COctetString::new(b"1234567890\0").unwrap()) .esme_addr_ton(Ton::Abbreviated) .esme_addr_npi(Npi::WapClientId) .esme_addr(COctetString::new(b"0987654321\0").unwrap()) .ms_availability_status(Some(MsAvailabilityStatus::Other(255))) .build(), ] } } ``` -------------------------------- ### Udh Creation and Access Source: https://docs.rs/rusmpp-core/latest/rusmpp_core/udhs/owned/struct.Udh.html Demonstrates how to create a Udh instance and access its properties. ```APIDOC ## Udh Struct Methods ### `new(value: impl Into) -> Self` Creates a new `Udh` from the given `UdhValue`. ### `id(&self) -> UdhId` Returns the UDH identifier. ### `length(&self) -> u8` Returns the UDH length (excluding the length field itself). ### `value(&self) -> Option<&UdhValue>` Returns a reference to the UDH value. ### `into_parts(self) -> UdhParts` Converts `Self` into its parts. ### `from_parts(parts: UdhParts) -> Self` Creates a new instance of `Self` from its parts. **Note:** This may create invalid instances. It’s up to the caller to ensure that the parts are valid. ``` -------------------------------- ### OctetString Compile-Fail Example Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/types/borrowed/octet_string.rs.html This example demonstrates a compile-time error when creating an OctetString with a length exceeding its maximum bound. ```rust #[allow(path_statements)] use crate::types::borrowed::octet_string::OctetString; // does not compile let string = OctetString::<10,5>::new(b"Hello"); ``` -------------------------------- ### Command Builder Initialization Source: https://docs.rs/rusmpp-core/latest/src/rusmpp_core/command/owned.rs.html Provides a static method to obtain a `CommandStatusBuilder`, which is the starting point for constructing a `Command` using a fluent builder pattern. This simplifies command creation by chaining method calls. ```rust impl Command { #[inline] pub fn builder() -> CommandStatusBuilder { Default::default() } } ```