### 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()
}
}
```