Skip to main content

Mib

Struct Mib 

Source
pub struct Mib {
Show 35 fields pub itsGnLocalGnAddr: GNAddress, pub itsGnLocalGnAddrConfMethod: LocalGnAddrConfMethod, pub itsGnProtocolVersion: u8, pub itsGnIsMobile: GnIsMobile, pub itsGnIfType: GnIfType, pub itsGnMinUpdateFrequencyEPV: u16, pub itsGnPaiInterval: u8, pub itsGnMaxSduSize: u16, pub itsGnMaxGeoNetworkingHeaderSize: u16, pub itsGnLifetimeLocTE: u16, pub itsGnSecurity: GnSecurity, pub itsGnSnDecapResultHandling: SnDecapResultHandling, pub itsGnLocationServiceMaxRetrans: u8, pub itsGnLocationServiceRetransmitTimer: u16, pub itsGnLocationServicePacketBufferSize: u16, pub itsGnBeaconServiceRetransmitTimer: u16, pub itsGnBeaconServiceMaxJitter: u16, pub itsGnDefaultHopLimit: u8, pub itsGnDPLLength: u8, pub itsGnMaxPacketLifetime: u16, pub itsGnDefaultPacketLifetime: u8, pub itsGnMaxPacketDataRate: u32, pub itsGnMaxPacketDataRateEmaBeta: u8, pub itsGnMaxGeoAreaSize: u16, pub itsGnMinPacketRepetitionInterval: u16, pub itsGnNonAreaForwardingAlgorithm: NonAreaForwardingAlgorithm, pub itsGnAreaForwardingAlgorithm: AreaForwardingAlgorithm, pub itsGnCbfMinTime: u16, pub itsGnCbfMaxTime: u16, pub itsGnDefaultMaxCommunicationRange: u16, pub itsGnBroadcastCBFDefSectorAngle: u8, pub itsGnUcForwardingPacketBufferSize: u16, pub itsGnBcForwardingPacketBufferSize: u16, pub itsGnCbfPacketBufferSize: u16, pub itsGnDefaultTrafficClass: u8,
}

Fields§

§itsGnLocalGnAddr: GNAddress§itsGnLocalGnAddrConfMethod: LocalGnAddrConfMethod§itsGnProtocolVersion: u8§itsGnIsMobile: GnIsMobile§itsGnIfType: GnIfType§itsGnMinUpdateFrequencyEPV: u16§itsGnPaiInterval: u8§itsGnMaxSduSize: u16§itsGnMaxGeoNetworkingHeaderSize: u16§itsGnLifetimeLocTE: u16§itsGnSecurity: GnSecurity§itsGnSnDecapResultHandling: SnDecapResultHandling§itsGnLocationServiceMaxRetrans: u8§itsGnLocationServiceRetransmitTimer: u16§itsGnLocationServicePacketBufferSize: u16§itsGnBeaconServiceRetransmitTimer: u16§itsGnBeaconServiceMaxJitter: u16§itsGnDefaultHopLimit: u8§itsGnDPLLength: u8§itsGnMaxPacketLifetime: u16§itsGnDefaultPacketLifetime: u8§itsGnMaxPacketDataRate: u32§itsGnMaxPacketDataRateEmaBeta: u8§itsGnMaxGeoAreaSize: u16§itsGnMinPacketRepetitionInterval: u16§itsGnNonAreaForwardingAlgorithm: NonAreaForwardingAlgorithm§itsGnAreaForwardingAlgorithm: AreaForwardingAlgorithm§itsGnCbfMinTime: u16§itsGnCbfMaxTime: u16§itsGnDefaultMaxCommunicationRange: u16§itsGnBroadcastCBFDefSectorAngle: u8§itsGnUcForwardingPacketBufferSize: u16§itsGnBcForwardingPacketBufferSize: u16§itsGnCbfPacketBufferSize: u16§itsGnDefaultTrafficClass: u8

Implementations§

Source§

impl Mib

Source

pub fn new() -> Self

Examples found in repository?
examples/bench_cam_tx.rs (line 57)
44fn main() {
45    let iface = env::args().nth(1).unwrap_or_else(|| "lo".to_string());
46    let duration_s = env::args()
47        .nth(2)
48        .and_then(|s| s.parse::<u64>().ok())
49        .unwrap_or(10);
50
51    println!("=== Benchmark: Maximum CAM TX throughput ===");
52    println!("Interface : {iface}");
53    println!("Duration  : {duration_s} s\n");
54
55    // ── MAC / MIB ─────────────────────────────────────────────────────────────
56    let mac = random_mac();
57    let mut mib = Mib::new();
58    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::PassengerCar, MID::new(mac));
59    mib.itsGnBeaconServiceRetransmitTimer = 0;
60
61    // ── Routers + link layer ──────────────────────────────────────────────────
62    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
63    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
64
65    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
66    RawLinkLayer::new(ll_to_gn_tx, gn_to_ll_rx, &iface, mac).start();
67    wire_routers(
68        &gn_handle,
69        &btp_handle,
70        ll_to_gn_rx,
71        gn_to_btp_rx,
72        btp_to_gn_rx,
73    );
74
75    // Seed GN position vector so packets are accepted downstream.
76    let mut epv = LongPositionVector::decode([0u8; 24]);
77    epv.update_from_gps(41.552, 2.134, 0.0, 0.0, true);
78    gn_handle.update_position_vector(epv);
79    thread::sleep(Duration::from_millis(50));
80
81    // ── Coder + template CAM ──────────────────────────────────────────────────
82    let station_id = u32::from_be_bytes([mac[2], mac[3], mac[4], mac[5]]);
83    let coder = CamCoder::new();
84    let template = make_cam(station_id);
85
86    // ── Benchmark loop ────────────────────────────────────────────────────────
87    println!("Sending CAMs as fast as possible…\n");
88    println!(
89        "{:>7}  {:>10}  {:>12}  {:>12}",
90        "time(s)", "total_sent", "rate(pkt/s)", "avg_enc(µs)"
91    );
92
93    let mut total_sent: u64 = 0;
94    let mut total_enc_us: u128 = 0;
95    let bench_start = Instant::now();
96    let bench_end = bench_start + Duration::from_secs(duration_s);
97    let mut win_start = Instant::now();
98    let mut win_sent: u64 = 0;
99
100    while Instant::now() < bench_end {
101        let t0 = Instant::now();
102        let data = match coder.encode(&template) {
103            Ok(d) => d,
104            Err(e) => {
105                eprintln!("[TX] Encode error: {e}");
106                continue;
107            }
108        };
109        let enc_us = t0.elapsed().as_micros();
110
111        btp_handle.send_btp_data_request(cam_btp_request(data));
112
113        total_sent += 1;
114        total_enc_us += enc_us;
115        win_sent += 1;
116
117        let win_elapsed = win_start.elapsed();
118        if win_elapsed >= Duration::from_secs(1) {
119            let pps = win_sent as f64 / win_elapsed.as_secs_f64();
120            let avg_enc = total_enc_us / total_sent.max(1) as u128;
121            println!(
122                "{:>7.1}  {:>10}  {:>12.1}  {:>12}",
123                bench_start.elapsed().as_secs_f64(),
124                total_sent,
125                pps,
126                avg_enc
127            );
128            win_start = Instant::now();
129            win_sent = 0;
130        }
131    }
132
133    // ── Summary ───────────────────────────────────────────────────────────────
134    let elapsed = bench_start.elapsed().as_secs_f64();
135    let avg_rate = total_sent as f64 / elapsed;
136    let avg_encode = total_enc_us / total_sent.max(1) as u128;
137
138    println!();
139    println!("=== CAM TX Results ===");
140    println!("  Total sent      : {total_sent}");
141    println!("  Elapsed         : {elapsed:.3} s");
142    println!("  Average rate    : {avg_rate:.1} pkt/s");
143    println!("  Avg encode time : {avg_encode} µs");
144}
More examples
Hide additional examples
examples/bench_cam_rx.rs (line 46)
33fn main() {
34    let iface = env::args().nth(1).unwrap_or_else(|| "lo".to_string());
35    let duration_s = env::args()
36        .nth(2)
37        .and_then(|s| s.parse::<u64>().ok())
38        .unwrap_or(30);
39
40    println!("=== Benchmark: Maximum CAM RX throughput ===");
41    println!("Interface : {iface}");
42    println!("Duration  : {duration_s} s\n");
43
44    // ── MAC / MIB ─────────────────────────────────────────────────────────────
45    let mac = random_mac();
46    let mut mib = Mib::new();
47    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::PassengerCar, MID::new(mac));
48    mib.itsGnBeaconServiceRetransmitTimer = 0;
49
50    // ── Routers + link layer ──────────────────────────────────────────────────
51    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
52    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
53
54    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
55    RawLinkLayer::new(ll_to_gn_tx, gn_to_ll_rx, &iface, mac).start();
56    wire_routers(
57        &gn_handle,
58        &btp_handle,
59        ll_to_gn_rx,
60        gn_to_btp_rx,
61        btp_to_gn_rx,
62    );
63
64    // Seed position vector.
65    let mut epv = LongPositionVector::decode([0u8; 24]);
66    epv.update_from_gps(41.552, 2.134, 0.0, 0.0, true);
67    gn_handle.update_position_vector(epv);
68    thread::sleep(Duration::from_millis(50));
69
70    // ── Register on BTP port 2001 ─────────────────────────────────────────────
71    let (ind_tx, ind_rx) = mpsc::channel::<BTPDataIndication>();
72    btp_handle.register_port(2001, ind_tx);
73
74    // ── Benchmark loop ────────────────────────────────────────────────────────
75    println!("Waiting for CAMs on port 2001…\n");
76    println!(
77        "{:>7}  {:>10}  {:>12}  {:>12}  {:>10}",
78        "time(s)", "total_recv", "rate(pkt/s)", "avg_dec(µs)", "errors"
79    );
80
81    let coder = CamCoder::new();
82    let mut total_recv: u64 = 0;
83    let mut total_errors: u64 = 0;
84    let mut total_dec_us: u128 = 0;
85    let bench_start = Instant::now();
86    let bench_end = bench_start + Duration::from_secs(duration_s);
87    let mut win_start = Instant::now();
88    let mut win_recv: u64 = 0;
89
90    loop {
91        let now = Instant::now();
92        if now >= bench_end {
93            break;
94        }
95
96        let timeout = (bench_end - now).min(Duration::from_millis(500));
97        match ind_rx.recv_timeout(timeout) {
98            Ok(ind) => {
99                let t0 = Instant::now();
100                match coder.decode(&ind.data) {
101                    Ok(_) => {}
102                    Err(e) => {
103                        total_errors += 1;
104                        eprintln!("[RX] Decode error: {e}");
105                    }
106                }
107                let dec_us = t0.elapsed().as_micros();
108                total_recv += 1;
109                total_dec_us += dec_us;
110                win_recv += 1;
111            }
112            Err(mpsc::RecvTimeoutError::Timeout) => {}
113            Err(mpsc::RecvTimeoutError::Disconnected) => break,
114        }
115
116        let win_elapsed = win_start.elapsed();
117        if win_elapsed >= Duration::from_secs(1) {
118            let pps = win_recv as f64 / win_elapsed.as_secs_f64();
119            let avg_dec = if total_recv > 0 {
120                total_dec_us / total_recv as u128
121            } else {
122                0
123            };
124            println!(
125                "{:>7.1}  {:>10}  {:>12.1}  {:>12}  {:>10}",
126                bench_start.elapsed().as_secs_f64(),
127                total_recv,
128                pps,
129                avg_dec,
130                total_errors
131            );
132            win_start = Instant::now();
133            win_recv = 0;
134        }
135    }
136
137    // ── Summary ───────────────────────────────────────────────────────────────
138    let elapsed = bench_start.elapsed().as_secs_f64();
139    let avg_rate = total_recv as f64 / elapsed;
140    let avg_decode = if total_recv > 0 {
141        total_dec_us / total_recv as u128
142    } else {
143        0
144    };
145
146    println!();
147    println!("=== CAM RX Results ===");
148    println!("  Total received  : {total_recv}");
149    println!("  Decode errors   : {total_errors}");
150    println!("  Elapsed         : {elapsed:.3} s");
151    println!("  Average rate    : {avg_rate:.1} pkt/s");
152    println!("  Avg decode time : {avg_decode} µs");
153}
examples/vam_sender_receiver.rs (line 72)
43fn main() {
44    // ── Parse optional interface argument ─────────────────────────────────────
45    let iface = env::args().nth(1).unwrap_or_else(|| "lo".to_string());
46
47    println!("=== VAM Sender/Receiver Example (VRU Awareness Service) ===");
48    println!("Interface: {}", iface);
49
50    // ── Generate a random locally-administered MAC ────────────────────────────
51    let mac = {
52        use std::time::{SystemTime, UNIX_EPOCH};
53        let seed = SystemTime::now()
54            .duration_since(UNIX_EPOCH)
55            .unwrap()
56            .subsec_nanos();
57        [
58            0x02u8,
59            (seed >> 24) as u8,
60            (seed >> 16) as u8,
61            (seed >> 8) as u8,
62            seed as u8,
63            0xBB,
64        ]
65    };
66    println!(
67        "MAC: {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
68        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
69    );
70
71    // ── MIB ───────────────────────────────────────────────────────────────────
72    let mut mib = Mib::new();
73    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::Cyclist, MID::new(mac));
74    mib.itsGnBeaconServiceRetransmitTimer = 0;
75
76    // ── Location Service ──────────────────────────────────────────────────────
77    //
78    // A single LocationService publishes GPS fixes to multiple subscribers.
79    // We subscribe twice: once for the GN router's position vector, and once
80    // for the VRU Awareness Service VAM generation.
81    let mut loc_svc = LocationService::new();
82    let gn_gps_rx = loc_svc.subscribe(); // → GN position vector updates
83    let vru_gps_rx = loc_svc.subscribe(); // → VAM transmission
84
85    // ── Spawn GeoNetworking router ────────────────────────────────────────────
86    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
87
88    // ── Spawn BTP router ──────────────────────────────────────────────────────
89    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
90
91    // ── Wire RawLinkLayer ─────────────────────────────────────────────────────
92    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
93    let raw_ll = RawLinkLayer::new(ll_to_gn_tx, gn_to_ll_rx, &iface, mac);
94    raw_ll.start();
95
96    // ── Wire threads ──────────────────────────────────────────────────────────
97
98    // LL → GN
99    let gn_h1 = gn_handle.clone();
100    thread::spawn(move || {
101        while let Ok(pkt) = ll_to_gn_rx.recv() {
102            gn_h1.send_incoming_packet(pkt);
103        }
104    });
105
106    // GN → BTP
107    let btp_h1 = btp_handle.clone();
108    thread::spawn(move || {
109        while let Ok(ind) = gn_to_btp_rx.recv() {
110            btp_h1.send_gn_data_indication(ind);
111        }
112    });
113
114    // BTP → GN
115    let gn_h2 = gn_handle.clone();
116    thread::spawn(move || {
117        while let Ok(req) = btp_to_gn_rx.recv() {
118            gn_h2.send_gn_data_request(req);
119        }
120    });
121
122    // ── Bridge: LocationService → GN router position vector ───────────────────
123    //
124    // Converts each GpsFix into a LongPositionVector and pushes it into the
125    // GeoNetworking router so the EPV in every outgoing GN header is current.
126    let gn_h3 = gn_handle.clone();
127    thread::spawn(move || {
128        while let Ok(fix) = gn_gps_rx.recv() {
129            let mut epv = LongPositionVector::decode([0u8; 24]);
130            epv.update_from_gps(
131                fix.latitude,
132                fix.longitude,
133                fix.speed_mps,
134                fix.heading_deg,
135                fix.pai,
136            );
137            gn_h3.update_position_vector(epv);
138        }
139    });
140
141    // ── VRU Awareness Service ─────────────────────────────────────────────────
142    //
143    // DeviceData carries static VRU metadata that goes into every VAM.
144    // station_id is derived from the MAC bytes; station_type 2 = cyclist.
145    let station_id = u32::from_be_bytes([mac[2], mac[3], mac[4], mac[5]]);
146    let device_data = DeviceData {
147        station_id,
148        station_type: 2, // cyclist
149    };
150
151    // VruAwarenessService::new returns the service handle plus a
152    // Receiver<Vam> on which decoded incoming VAMs arrive.
153    let (vru_svc, vam_rx) = VruAwarenessService::new(btp_handle.clone(), device_data);
154
155    // start() consumes the service handle and spawns the TX + RX threads.
156    vru_svc.start(vru_gps_rx);
157
158    // ── Decoded VAM printer ───────────────────────────────────────────────────
159    thread::spawn(move || {
160        while let Ok(vam) = vam_rx.recv() {
161            let lat = vam
162                .vam
163                .vam_parameters
164                .basic_container
165                .reference_position
166                .latitude
167                .0 as f64
168                / 1e7;
169            let lon = vam
170                .vam
171                .vam_parameters
172                .basic_container
173                .reference_position
174                .longitude
175                .0 as f64
176                / 1e7;
177            println!(
178                "[VAM RX] station={:>10}  lat={:.5}  lon={:.5}",
179                vam.header.0.station_id.0, lat, lon,
180            );
181        }
182    });
183
184    // ── GPS publisher (simulates a real GNSS sensor at 1 Hz) ──────────────────
185    //
186    // In a real application this thread would read from gpsd or a serial port.
187    // Wait briefly for the routers to finish initialising.
188    thread::sleep(Duration::from_millis(100));
189    println!("Publishing GPS fixes @ 10 Hz — Ctrl+C to stop\n");
190
191    loop {
192        thread::sleep(Duration::from_millis(100));
193        // 41.552°N  2.134°E — Parc Tecnològic del Vallès
194        loc_svc.publish(GpsFix {
195            latitude: 41.552,
196            longitude: 2.134,
197            altitude_m: 120.0,
198            speed_mps: 1.5,
199            heading_deg: 90.0,
200            pai: true,
201        });
202    }
203}
examples/denm_sender_receiver.rs (line 77)
48fn main() {
49    // ── Parse optional interface argument ─────────────────────────────────────
50    let iface = env::args().nth(1).unwrap_or_else(|| "lo".to_string());
51
52    println!("=== DENM Sender/Receiver Example (DEN Service) ===");
53    println!("Interface: {}", iface);
54
55    // ── Generate a random locally-administered MAC ────────────────────────────
56    let mac = {
57        use std::time::{SystemTime, UNIX_EPOCH};
58        let seed = SystemTime::now()
59            .duration_since(UNIX_EPOCH)
60            .unwrap()
61            .subsec_nanos();
62        [
63            0x02u8,
64            (seed >> 24) as u8,
65            (seed >> 16) as u8,
66            (seed >> 8) as u8,
67            seed as u8,
68            0xCC,
69        ]
70    };
71    println!(
72        "MAC: {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
73        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
74    );
75
76    // ── MIB ───────────────────────────────────────────────────────────────────
77    let mut mib = Mib::new();
78    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::PassengerCar, MID::new(mac));
79    mib.itsGnBeaconServiceRetransmitTimer = 0;
80
81    // ── Location Service ──────────────────────────────────────────────────────
82    //
83    // A single LocationService publishes GPS fixes.  We subscribe once for the
84    // GN router's position vector updates.
85    let mut loc_svc = LocationService::new();
86    let gn_gps_rx = loc_svc.subscribe();
87
88    // ── Spawn GeoNetworking router ────────────────────────────────────────────
89    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
90
91    // ── Spawn BTP router ──────────────────────────────────────────────────────
92    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
93
94    // ── Wire RawLinkLayer ─────────────────────────────────────────────────────
95    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
96    let raw_ll = RawLinkLayer::new(ll_to_gn_tx, gn_to_ll_rx, &iface, mac);
97    raw_ll.start();
98
99    // ── Wire threads ──────────────────────────────────────────────────────────
100
101    // LL → GN
102    let gn_h1 = gn_handle.clone();
103    thread::spawn(move || {
104        while let Ok(pkt) = ll_to_gn_rx.recv() {
105            gn_h1.send_incoming_packet(pkt);
106        }
107    });
108
109    // GN → BTP
110    let btp_h1 = btp_handle.clone();
111    thread::spawn(move || {
112        while let Ok(ind) = gn_to_btp_rx.recv() {
113            btp_h1.send_gn_data_indication(ind);
114        }
115    });
116
117    // BTP → GN
118    let gn_h2 = gn_handle.clone();
119    thread::spawn(move || {
120        while let Ok(req) = btp_to_gn_rx.recv() {
121            gn_h2.send_gn_data_request(req);
122        }
123    });
124
125    // ── Bridge: LocationService → GN router position vector ───────────────────
126    let gn_h3 = gn_handle.clone();
127    thread::spawn(move || {
128        while let Ok(fix) = gn_gps_rx.recv() {
129            let mut epv = LongPositionVector::decode([0u8; 24]);
130            epv.update_from_gps(
131                fix.latitude,
132                fix.longitude,
133                fix.speed_mps,
134                fix.heading_deg,
135                fix.pai,
136            );
137            gn_h3.update_position_vector(epv);
138        }
139    });
140
141    // ── DEN Service ───────────────────────────────────────────────────────────
142    let station_id = u32::from_be_bytes([mac[2], mac[3], mac[4], mac[5]]);
143    let vehicle_data = VehicleData {
144        station_id,
145        station_type: 5, // passengerCar
146    };
147
148    // DecentralizedEnvironmentalNotificationService::new returns the service
149    // handle plus a Receiver<Denm> on which decoded incoming DENMs arrive.
150    // The reception thread is started immediately (registers BTP port 2002).
151    let (den_svc, denm_rx) =
152        DecentralizedEnvironmentalNotificationService::new(btp_handle.clone(), vehicle_data);
153
154    // ── Decoded DENM printer ──────────────────────────────────────────────────
155    thread::spawn(move || {
156        while let Ok(denm) = denm_rx.recv() {
157            let lat = denm.denm.management.event_position.latitude.0 as f64 / 1e7;
158            let lon = denm.denm.management.event_position.longitude.0 as f64 / 1e7;
159            let seq = denm.denm.management.action_id.sequence_number.0;
160            println!(
161                "[DENM RX] station={:>10}  seq={:>5}  event_lat={:.5}  event_lon={:.5}",
162                denm.header.station_id.0, seq, lat, lon,
163            );
164        }
165    });
166
167    // ── Publish initial GPS fix to initialise the GN router ───────────────────
168    thread::sleep(Duration::from_millis(100));
169
170    // Publish position fixes to keep the GN position vector up to date.
171    let gps_fix = GpsFix {
172        latitude: 41.552,
173        longitude: 2.134,
174        altitude_m: 120.0,
175        speed_mps: 14.0, // ~50 km/h
176        heading_deg: 90.0,
177        pai: true,
178    };
179    loc_svc.publish(gps_fix);
180
181    // ── Trigger DENM: Road Hazard (accident) at current position ──────────────
182    //
183    // Send 1 DENM/s for 30 s, 1 000 m geo-broadcast circle.
184    println!("Triggering road-hazard DENM (accident) for 30 s @ 1 Hz");
185    den_svc.trigger_denm(DENRequest {
186        event_latitude: gps_fix.latitude,
187        event_longitude: gps_fix.longitude,
188        event_altitude_m: gps_fix.altitude_m,
189        cause_code: CauseCodeChoice::accident2(AccidentSubCauseCode(0)),
190        information_quality: 4,
191        event_speed_raw: (gps_fix.speed_mps * 100.0) as u16,
192        event_heading_raw: (gps_fix.heading_deg * 10.0) as u16,
193        denm_interval_ms: 1_000,
194        time_period_ms: 30_000,
195        relevance_radius_m: 1_000,
196    });
197
198    // ── GPS publisher loop ────────────────────────────────────────────────────
199    println!("Publishing GPS fixes @ 1 Hz — Ctrl+C to stop\n");
200    loop {
201        thread::sleep(Duration::from_secs(1));
202        loc_svc.publish(gps_fix);
203    }
204}
examples/cam_sender_receiver.rs (line 76)
47fn main() {
48    // ── Parse optional interface argument ────────────────────────────────────
49    let iface = env::args().nth(1).unwrap_or_else(|| "lo".to_string());
50
51    println!("=== CAM Sender/Receiver Example (CA Basic Service) ===");
52    println!("Interface: {}", iface);
53
54    // ── Generate a random locally-administered MAC ────────────────────────
55    let mac = {
56        use std::time::{SystemTime, UNIX_EPOCH};
57        let seed = SystemTime::now()
58            .duration_since(UNIX_EPOCH)
59            .unwrap()
60            .subsec_nanos();
61        [
62            0x02u8,
63            (seed >> 24) as u8,
64            (seed >> 16) as u8,
65            (seed >> 8) as u8,
66            seed as u8,
67            0xAA,
68        ]
69    };
70    println!(
71        "MAC: {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
72        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
73    );
74
75    // ── MIB ──────────────────────────────────────────────────────────────────
76    let mut mib = Mib::new();
77    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::PassengerCar, MID::new(mac));
78    mib.itsGnBeaconServiceRetransmitTimer = 0;
79
80    // ── Location Service ─────────────────────────────────────────────────────
81    //
82    // A single LocationService publishes GPS fixes to multiple subscribers.
83    // We subscribe twice: once for the GN router's position vector, and once
84    // for the CA Basic Service CAM generation.
85    let mut loc_svc = LocationService::new();
86    let gn_gps_rx = loc_svc.subscribe(); // → GN position vector updates
87    let ca_gps_rx = loc_svc.subscribe(); // → CAM transmission
88
89    // ── Spawn GeoNetworking router ────────────────────────────────────────────
90    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
91
92    // ── Spawn BTP router ─────────────────────────────────────────────────────
93    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
94
95    // ── Wire RawLinkLayer ────────────────────────────────────────────────────
96    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
97    let raw_ll = RawLinkLayer::new(ll_to_gn_tx, gn_to_ll_rx, &iface, mac);
98    raw_ll.start();
99
100    // ── Wire threads ─────────────────────────────────────────────────────────
101
102    // LL → GN
103    let gn_h1 = gn_handle.clone();
104    thread::spawn(move || {
105        while let Ok(pkt) = ll_to_gn_rx.recv() {
106            gn_h1.send_incoming_packet(pkt);
107        }
108    });
109
110    // GN → BTP
111    let btp_h1 = btp_handle.clone();
112    thread::spawn(move || {
113        while let Ok(ind) = gn_to_btp_rx.recv() {
114            btp_h1.send_gn_data_indication(ind);
115        }
116    });
117
118    // BTP → GN
119    let gn_h2 = gn_handle.clone();
120    thread::spawn(move || {
121        while let Ok(req) = btp_to_gn_rx.recv() {
122            gn_h2.send_gn_data_request(req);
123        }
124    });
125
126    // ── Bridge: LocationService → GN router position vector ──────────────────
127    //
128    // Converts each GpsFix into a LongPositionVector and pushes it into the
129    // GeoNetworking router so the EPV in every outgoing GN header is current.
130    let gn_h3 = gn_handle.clone();
131    thread::spawn(move || {
132        while let Ok(fix) = gn_gps_rx.recv() {
133            let mut epv = LongPositionVector::decode([0u8; 24]);
134            epv.update_from_gps(
135                fix.latitude,
136                fix.longitude,
137                fix.speed_mps,
138                fix.heading_deg,
139                fix.pai,
140            );
141            gn_h3.update_position_vector(epv);
142        }
143    });
144
145    // ── Local Dynamic Map ─────────────────────────────────────────────────────
146    //
147    // Create the LDM centred on the simulated GPS position with a 5 km radius.
148    // Parc Tecnològic del Vallès: 41.552°N 2.134°E → ETSI integers × 1e7.
149    let ldm = LdmFacility::new(415_520_000, 21_340_000, 5_000.0);
150
151    // Register this node as a CAM data provider and consumer.
152    ldm.if_ldm_3
153        .register_data_provider(RegisterDataProviderReq {
154            application_id: ITS_AID_CAM,
155        });
156    ldm.if_ldm_4
157        .register_data_consumer(RegisterDataConsumerReq {
158            application_id: ITS_AID_CAM,
159        });
160
161    // ── CA Basic Service ─────────────────────────────────────────────────────
162    //
163    // VehicleData carries static vehicle metadata that goes into every CAM.
164    // station_id should match the GN address mid bytes in a real deployment.
165    let station_id = u32::from_be_bytes([mac[2], mac[3], mac[4], mac[5]]);
166    let vehicle_data = VehicleData {
167        station_id,
168        ..VehicleData::default() // PassengerCar, unavailable lengths
169    };
170
171    // Pass Some(ldm) so every received CAM is stored in the LDM before being
172    // forwarded.  The _cam_rx channel is still available for direct consumers
173    // but in this example we read via IF.LDM.4 instead.
174    let (ca_svc, _cam_rx) =
175        CooperativeAwarenessBasicService::new(btp_handle.clone(), vehicle_data, Some(ldm.clone()));
176
177    // start() consumes the service handle and spawns the TX + RX threads.
178    ca_svc.start(ca_gps_rx);
179
180    // ── LDM query printer ─────────────────────────────────────────────────────
181    //
182    // Every second, query the LDM for all CAM records and print them.
183    // This uses the ETSI IF.LDM.4 interface and confirms that received CAMs
184    // are correctly stored and retrievable.
185    let ldm_reader = ldm.clone();
186    thread::spawn(move || loop {
187        thread::sleep(Duration::from_secs(1));
188        let resp = ldm_reader
189            .if_ldm_4
190            .request_data_objects(RequestDataObjectsReq {
191                application_id: ITS_AID_CAM,
192                data_object_types: vec![ITS_AID_CAM],
193                filter: None,
194                order: None,
195                max_results: None,
196            });
197        if resp.data_objects.is_empty() {
198            println!("[LDM] No CAM records in store");
199        } else {
200            println!("[LDM] {} CAM record(s):", resp.data_objects.len());
201            for entry in &resp.data_objects {
202                if let ItsDataObject::Cam(cam) = &entry.data_object {
203                    let lat = cam
204                        .cam
205                        .cam_parameters
206                        .basic_container
207                        .reference_position
208                        .latitude
209                        .0 as f64
210                        / 1e7;
211                    let lon = cam
212                        .cam
213                        .cam_parameters
214                        .basic_container
215                        .reference_position
216                        .longitude
217                        .0 as f64
218                        / 1e7;
219                    println!(
220                        "  [LDM CAM] record={:>5} station={:>10}  lat={:.5}  lon={:.5}",
221                        entry.record_id, cam.header.station_id.0, lat, lon,
222                    );
223                }
224            }
225        }
226    });
227
228    // ── GPS publisher (simulates a real GNSS sensor at 1 Hz) ─────────────────
229    //
230    // In a real application this thread would read from gpsd or a serial port.
231    // Wait briefly for the routers to finish initialising.
232    thread::sleep(Duration::from_millis(100));
233    println!("Publishing GPS fixes @ 10 Hz — Ctrl+C to stop\n");
234
235    loop {
236        thread::sleep(Duration::from_millis(100));
237        // 41.552°N  2.134°E — Parc Tecnològic del Vallès
238        loc_svc.publish(GpsFix {
239            latitude: 41.552,
240            longitude: 2.134,
241            altitude_m: 120.0,
242            speed_mps: 0.0,
243            heading_deg: 0.0,
244            pai: true,
245        });
246    }
247}
examples/secured_vam_sender_receiver.rs (line 186)
118fn main() {
119    // ── Parse arguments ──────────────────────────────────────────────────
120    let args: Vec<String> = env::args().collect();
121    let mut at_index: usize = 1;
122    let mut iface = "lo".to_string();
123
124    let mut i = 1;
125    while i < args.len() {
126        match args[i].as_str() {
127            "--at" => {
128                i += 1;
129                at_index = args[i].parse::<usize>().expect("--at must be 1 or 2");
130                assert!(at_index == 1 || at_index == 2, "--at must be 1 or 2");
131            }
132            "--iface" | "-i" => {
133                i += 1;
134                iface = args[i].clone();
135            }
136            other => {
137                // Positional argument: interface name
138                iface = other.to_string();
139            }
140        }
141        i += 1;
142    }
143
144    println!("=== Secured VAM Sender/Receiver (VRU Awareness Service) ===");
145    println!("AT index: {}", at_index);
146    println!("Interface: {}", iface);
147
148    // ── Build security stack ─────────────────────────────────────────────
149    let sign_service = build_security_stack(at_index);
150    println!(
151        "Security stack loaded. Own AT HashedId8: {:02x?}",
152        sign_service
153            .cert_library
154            .own_certificates
155            .keys()
156            .next()
157            .unwrap()
158    );
159
160    // Wrap in Arc<Mutex> so it can be shared between threads
161    let sign_service = Arc::new(Mutex::new(sign_service));
162
163    // ── Generate a random locally-administered MAC ───────────────────────
164    let mac = {
165        use std::time::{SystemTime, UNIX_EPOCH};
166        let seed = SystemTime::now()
167            .duration_since(UNIX_EPOCH)
168            .unwrap()
169            .subsec_nanos()
170            ^ (at_index as u32 * 0x1234_5678); // different seed per AT
171        [
172            0x02u8,
173            (seed >> 24) as u8,
174            (seed >> 16) as u8,
175            (seed >> 8) as u8,
176            seed as u8,
177            at_index as u8,
178        ]
179    };
180    println!(
181        "MAC: {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
182        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
183    );
184
185    // ── MIB ──────────────────────────────────────────────────────────────
186    let mut mib = Mib::new();
187    mib.itsGnLocalGnAddr = GNAddress::new(M::GnMulticast, ST::Cyclist, MID::new(mac));
188    mib.itsGnBeaconServiceRetransmitTimer = 0;
189
190    // ── Location Service ─────────────────────────────────────────────────
191    let mut loc_svc = LocationService::new();
192    let gn_gps_rx = loc_svc.subscribe();
193    let vru_gps_rx = loc_svc.subscribe();
194
195    // ── Spawn GN router and BTP router ───────────────────────────────────
196    let (gn_handle, gn_to_ll_rx, gn_to_btp_rx) = GNRouter::spawn(mib, None, None, None);
197    let (btp_handle, btp_to_gn_rx) = BTPRouter::spawn(mib);
198
199    // ── Wire RawLinkLayer ────────────────────────────────────────────────
200    let (ll_to_gn_tx, ll_to_gn_rx) = mpsc::channel::<Vec<u8>>();
201
202    // ── Security middleware: TX path ─────────────────────────────────────
203    //
204    // Intercept packets from GN router → link layer.
205    // Sign the payload (CommonHeader + extended header + data) and wrap
206    // in a secured GN packet with BasicNH::SecuredPacket.
207    let (secured_ll_tx, secured_ll_rx) = mpsc::channel::<Vec<u8>>();
208    let sign_svc_tx = Arc::clone(&sign_service);
209    thread::spawn(move || {
210        while let Ok(packet) = gn_to_ll_rx.recv() {
211            if packet.len() < 4 {
212                let _ = secured_ll_tx.send(packet);
213                continue;
214            }
215            let bh_bytes: [u8; 4] = packet[0..4].try_into().unwrap();
216            let bh = BasicHeader::decode(bh_bytes);
217
218            match bh.nh {
219                BasicNH::CommonHeader if packet.len() > 4 => {
220                    let inner_payload = &packet[4..];
221
222                    let request = SNSignRequest {
223                        tbs_message: inner_payload.to_vec(),
224                        its_aid: ITS_AID_VAM,
225                        permissions: vec![],
226                        generation_location: None,
227                    };
228
229                    let sec_message = {
230                        let mut svc = sign_svc_tx.lock().unwrap();
231                        svc.sign_request(&request).sec_message
232                    };
233
234                    // Build new packet: BasicHeader(nh=SecuredPacket) + sec_message
235                    let mut new_bh = bh;
236                    new_bh.nh = BasicNH::SecuredPacket;
237                    let secured_packet: Vec<u8> = new_bh
238                        .encode()
239                        .iter()
240                        .copied()
241                        .chain(sec_message.iter().copied())
242                        .collect();
243                    let _ = secured_ll_tx.send(secured_packet);
244                }
245                _ => {
246                    // Pass through (e.g. beacons)
247                    let _ = secured_ll_tx.send(packet);
248                }
249            }
250        }
251    });
252
253    // The link layer reads from secured_ll_rx (post-signing)
254    let raw_ll = RawLinkLayer::new(ll_to_gn_tx, secured_ll_rx, &iface, mac);
255    raw_ll.start();
256
257    // ── Security middleware: RX path ─────────────────────────────────────
258    //
259    // Intercept packets from link layer → GN router.
260    // If BasicNH::SecuredPacket, verify and extract, then forward
261    // with BasicNH::CommonHeader.
262    let gn_h_rx = gn_handle.clone();
263    let sign_svc_rx = Arc::clone(&sign_service);
264    thread::spawn(move || {
265        while let Ok(packet) = ll_to_gn_rx.recv() {
266            if packet.len() < 4 {
267                gn_h_rx.send_incoming_packet(packet);
268                continue;
269            }
270            let bh_bytes: [u8; 4] = packet[0..4].try_into().unwrap();
271            let bh = BasicHeader::decode(bh_bytes);
272
273            match bh.nh {
274                BasicNH::SecuredPacket if packet.len() > 4 => {
275                    let sec_message = &packet[4..];
276                    let request = SNVerifyRequest {
277                        message: sec_message.to_vec(),
278                    };
279
280                    let (confirm, _events) = {
281                        let mut svc = sign_svc_rx.lock().unwrap();
282                        let svc = &mut *svc;
283                        let result = verify_message(&request, &svc.backend, &mut svc.cert_library);
284                        // Process VerifyEvents for P2PCD
285                        for event in &result.1 {
286                            match event {
287                                VerifyEvent::UnknownAt(h8) => {
288                                    svc.notify_unknown_at(h8);
289                                }
290                                VerifyEvent::InlineP2pcdRequest(h3s) => {
291                                    svc.notify_inline_p2pcd_request(h3s);
292                                }
293                                VerifyEvent::ReceivedCaCertificate(cert) => {
294                                    svc.notify_received_ca_certificate(cert.as_ref().clone());
295                                }
296                            }
297                        }
298                        result
299                    };
300
301                    if confirm.report == ReportVerify::Success {
302                        println!(
303                            "[SEC RX] Verified OK — ITS-AID={}, cert={:02x?}",
304                            confirm.its_aid,
305                            &confirm.certificate_id[..],
306                        );
307                        // Rebuild the packet: BasicHeader(nh=CommonHeader) + plain_message
308                        let mut new_bh = bh;
309                        new_bh.nh = BasicNH::CommonHeader;
310                        let plain_packet: Vec<u8> = new_bh
311                            .encode()
312                            .iter()
313                            .copied()
314                            .chain(confirm.plain_message.iter().copied())
315                            .collect();
316                        gn_h_rx.send_incoming_packet(plain_packet);
317                    } else {
318                        eprintln!("[SEC RX] Verification failed: {:?}", confirm.report);
319                    }
320                }
321                _ => {
322                    // Non-secured packet — forward directly
323                    gn_h_rx.send_incoming_packet(packet);
324                }
325            }
326        }
327    });
328
329    // ── GN → BTP ─────────────────────────────────────────────────────────
330    let btp_h1 = btp_handle.clone();
331    thread::spawn(move || {
332        while let Ok(ind) = gn_to_btp_rx.recv() {
333            btp_h1.send_gn_data_indication(ind);
334        }
335    });
336
337    // ── BTP → GN ─────────────────────────────────────────────────────────
338    let gn_h2 = gn_handle.clone();
339    thread::spawn(move || {
340        while let Ok(req) = btp_to_gn_rx.recv() {
341            gn_h2.send_gn_data_request(req);
342        }
343    });
344
345    // ── LocationService → GN position vector ─────────────────────────────
346    let gn_h3 = gn_handle.clone();
347    thread::spawn(move || {
348        while let Ok(fix) = gn_gps_rx.recv() {
349            let mut epv = LongPositionVector::decode([0u8; 24]);
350            epv.update_from_gps(
351                fix.latitude,
352                fix.longitude,
353                fix.speed_mps,
354                fix.heading_deg,
355                fix.pai,
356            );
357            gn_h3.update_position_vector(epv);
358        }
359    });
360
361    // ── VRU Awareness Service ────────────────────────────────────────────
362    let station_id = u32::from_be_bytes([mac[2], mac[3], mac[4], mac[5]]);
363    let device_data = DeviceData {
364        station_id,
365        station_type: 2, // cyclist
366    };
367
368    let (vru_svc, vam_rx) = VruAwarenessService::new(btp_handle.clone(), device_data);
369    vru_svc.start(vru_gps_rx);
370
371    // ── Decoded VAM printer ──────────────────────────────────────────────
372    thread::spawn(move || {
373        while let Ok(vam) = vam_rx.recv() {
374            let lat = vam
375                .vam
376                .vam_parameters
377                .basic_container
378                .reference_position
379                .latitude
380                .0 as f64
381                / 1e7;
382            let lon = vam
383                .vam
384                .vam_parameters
385                .basic_container
386                .reference_position
387                .longitude
388                .0 as f64
389                / 1e7;
390            println!(
391                "[VAM RX] station={:>10}  lat={:.5}  lon={:.5}",
392                vam.header.0.station_id.0, lat, lon,
393            );
394        }
395    });
396
397    // ── GPS publisher (simulates a VRU GNSS sensor at 10 Hz) ─────────────
398    thread::sleep(Duration::from_millis(100));
399    println!("Publishing GPS fixes @ 10 Hz — Ctrl+C to stop\n");
400
401    loop {
402        thread::sleep(Duration::from_millis(100));
403        // 41.552°N  2.134°E — Parc Tecnològic del Vallès
404        loc_svc.publish(GpsFix {
405            latitude: 41.552,
406            longitude: 2.134,
407            altitude_m: 120.0,
408            speed_mps: 1.5,
409            heading_deg: 90.0,
410            pai: true,
411        });
412    }
413}

Trait Implementations§

Source§

impl Clone for Mib

Source§

fn clone(&self) -> Mib

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Mib

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Mib

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for Mib

Source§

fn eq(&self, other: &Mib) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Mib

Source§

impl StructuralPartialEq for Mib

Auto Trait Implementations§

§

impl Freeze for Mib

§

impl RefUnwindSafe for Mib

§

impl Send for Mib

§

impl Sync for Mib

§

impl Unpin for Mib

§

impl UnsafeUnpin for Mib

§

impl UnwindSafe for Mib

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V