pub struct CharacteristicWriter { /* private fields */ }
Available on crate feature bluetoothd only.
Expand description

Streams data to a characteristic with low overhead.

Implementations§

source§

impl CharacteristicWriter

source

pub fn adapter_name(&self) -> &str

Name of adapter.

source

pub fn device_address(&self) -> Address

Address of remote device.

Examples found in repository?
examples/gatt_server_io.rs (line 97)
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;

    println!("Advertising on Bluetooth adapter {} with address {}", adapter.name(), adapter.address().await?);
    let mut manufacturer_data = BTreeMap::new();
    manufacturer_data.insert(MANUFACTURER_ID, vec![0x21, 0x22, 0x23, 0x24]);
    let le_advertisement = Advertisement {
        service_uuids: vec![SERVICE_UUID].into_iter().collect(),
        manufacturer_data,
        discoverable: Some(true),
        local_name: Some("gatt_server".to_string()),
        ..Default::default()
    };
    let adv_handle = adapter.advertise(le_advertisement).await?;

    println!("Serving GATT service on Bluetooth adapter {}", adapter.name());
    let (service_control, service_handle) = service_control();
    let (char_control, char_handle) = characteristic_control();
    let app = Application {
        services: vec![Service {
            uuid: SERVICE_UUID,
            primary: true,
            characteristics: vec![Characteristic {
                uuid: CHARACTERISTIC_UUID,
                write: Some(CharacteristicWrite {
                    write: true,
                    write_without_response: true,
                    method: CharacteristicWriteMethod::Io,
                    ..Default::default()
                }),
                notify: Some(CharacteristicNotify {
                    notify: true,
                    method: CharacteristicNotifyMethod::Io,
                    ..Default::default()
                }),
                control_handle: char_handle,
                ..Default::default()
            }],
            control_handle: service_handle,
            ..Default::default()
        }],
        ..Default::default()
    };
    let app_handle = adapter.serve_gatt_application(app).await?;

    println!("Service handle is 0x{:x}", service_control.handle()?);
    println!("Characteristic handle is 0x{:x}", char_control.handle()?);

    println!("Service ready. Press enter to quit.");
    let stdin = BufReader::new(tokio::io::stdin());
    let mut lines = stdin.lines();

    let mut value: Vec<u8> = vec![0x10, 0x01, 0x01, 0x10];
    let mut read_buf = Vec::new();
    let mut reader_opt: Option<CharacteristicReader> = None;
    let mut writer_opt: Option<CharacteristicWriter> = None;
    let mut interval = interval(Duration::from_secs(1));
    pin_mut!(char_control);

    loop {
        tokio::select! {
            _ = lines.next_line() => break,
            evt = char_control.next() => {
                match evt {
                    Some(CharacteristicControlEvent::Write(req)) => {
                        println!("Accepting write event with MTU {} from {}", req.mtu(), req.device_address());
                        read_buf = vec![0; req.mtu()];
                        reader_opt = Some(req.accept()?);
                    },
                    Some(CharacteristicControlEvent::Notify(notifier)) => {
                        println!("Accepting notify request event with MTU {} from {}", notifier.mtu(), notifier.device_address());
                        writer_opt = Some(notifier);
                    },
                    None => break,
                }
            }
            _ = interval.tick() => {
                println!("Decrementing each element by one");
                for v in &mut *value {
                    *v = v.saturating_sub(1);
                }
                println!("Value is {:x?}", &value);
                if let Some(writer) = writer_opt.as_mut() {
                    println!("Notifying with value {:x?}", &value);
                    if let Err(err) = writer.write(&value).await {
                        println!("Notification stream error: {}", &err);
                        writer_opt = None;
                    }
                }
            }
            read_res = async {
                match &mut reader_opt {
                    Some(reader) => reader.read(&mut read_buf).await,
                    None => future::pending().await,
                }
            } => {
                match read_res {
                    Ok(0) => {
                        println!("Write stream ended");
                        reader_opt = None;
                    }
                    Ok(n) => {
                        value = read_buf[0..n].to_vec();
                        println!("Write request with {} bytes: {:x?}", n, &value);
                    }
                    Err(err) => {
                        println!("Write stream error: {}", &err);
                        reader_opt = None;
                    }
                }
            }
        }
    }

    println!("Removing service and advertisement");
    drop(app_handle);
    drop(adv_handle);
    sleep(Duration::from_secs(1)).await;

    Ok(())
}
source

pub fn mtu(&self) -> usize

Maximum transmission unit.

Examples found in repository?
examples/gatt_echo_client.rs (line 66)
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
async fn exercise_characteristic(char: &Characteristic) -> Result<()> {
    let mut write_io = char.write_io().await?;
    println!("    Obtained write IO with MTU {} bytes", write_io.mtu());
    let mut notify_io = char.notify_io().await?;
    println!("    Obtained notification IO with MTU {} bytes", notify_io.mtu());

    // Flush notify buffer.
    let mut buf = [0; 1024];
    while let Ok(Ok(_)) = timeout(Duration::from_secs(1), notify_io.read(&mut buf)).await {}

    let mut rng = rand::thread_rng();
    for i in 0..1024 {
        let mut len = rng.gen_range(0..20000);

        // Try to trigger packet reordering over EATT.
        if i % 10 == 0 {
            // Big packet is split into multiple small packets.
            // (by L2CAP layer, because GATT MTU is bigger than L2CAP MTU)
            len = write_io.mtu(); // 512
        }
        if i % 10 == 1 {
            // Small packet can use different L2CAP channel when EATT is enabled.
            len = 20;
        }
        // Thus small packet can arrive before big packet.
        // The solution is to disable EATT in /etc/bluetooth/main.conf.

        println!("    Test iteration {i} with data size {len}");
        let data: Vec<u8> = (0..len).map(|_| rng.gen()).collect();

        // We must read back the data while sending, otherwise the connection
        // buffer will overrun and we will lose data.
        let read_task = tokio::spawn(async move {
            let mut echo_buf = vec![0u8; len];
            let res = match notify_io.read_exact(&mut echo_buf).await {
                Ok(_) => Ok(echo_buf),
                Err(err) => Err(err),
            };
            (notify_io, res)
        });

        // Note that write_all will automatically split the buffer into
        // multiple writes of MTU size.
        write_io.write_all(&data).await.expect("write failed");

        println!("    Waiting for echo");
        let (notify_io_back, res) = read_task.await.unwrap();
        notify_io = notify_io_back;
        let echo_buf = res.expect("read failed");

        if echo_buf != data {
            println!();
            println!("Echo data mismatch!");
            println!("Send data:     {:x?}", &data);
            println!("Received data: {:x?}", &echo_buf);
            println!();
            println!("By 512 blocks:");
            for (sent, recv) in data.chunks(512).zip(echo_buf.chunks(512)) {
                println!();
                println!(
                    "Send: {:x?} ... {:x?}",
                    &sent[0..4.min(sent.len())],
                    &sent[sent.len().saturating_sub(4)..]
                );
                println!(
                    "Recv: {:x?} ... {:x?}",
                    &recv[0..4.min(recv.len())],
                    &recv[recv.len().saturating_sub(4)..]
                );
            }
            println!();

            panic!("echoed data does not match sent data");
        }
        println!("    Data matches");
    }

    println!("    Test okay");
    Ok(())
}
More examples
Hide additional examples
examples/gatt_echo_server.rs (line 86)
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;

    println!("Advertising on Bluetooth adapter {} with address {}", adapter.name(), adapter.address().await?);
    let le_advertisement = Advertisement {
        service_uuids: vec![SERVICE_UUID].into_iter().collect(),
        discoverable: Some(true),
        local_name: Some("gatt_echo_server".to_string()),
        ..Default::default()
    };
    let adv_handle = adapter.advertise(le_advertisement).await?;

    println!("Serving GATT echo service on Bluetooth adapter {}", adapter.name());
    let (char_control, char_handle) = characteristic_control();
    let app = Application {
        services: vec![Service {
            uuid: SERVICE_UUID,
            primary: true,
            characteristics: vec![Characteristic {
                uuid: CHARACTERISTIC_UUID,
                write: Some(CharacteristicWrite {
                    write_without_response: true,
                    method: CharacteristicWriteMethod::Io,
                    ..Default::default()
                }),
                notify: Some(CharacteristicNotify {
                    notify: true,
                    method: CharacteristicNotifyMethod::Io,
                    ..Default::default()
                }),
                control_handle: char_handle,
                ..Default::default()
            }],
            ..Default::default()
        }],
        ..Default::default()
    };
    let app_handle = adapter.serve_gatt_application(app).await?;

    println!("Echo service ready. Press enter to quit.");
    let stdin = BufReader::new(tokio::io::stdin());
    let mut lines = stdin.lines();

    let mut read_buf = Vec::new();
    let mut reader_opt: Option<CharacteristicReader> = None;
    let mut writer_opt: Option<CharacteristicWriter> = None;
    pin_mut!(char_control);

    loop {
        tokio::select! {
            _ = lines.next_line() => break,
            evt = char_control.next() => {
                match evt {
                    Some(CharacteristicControlEvent::Write(req)) => {
                        println!("Accepting write request event with MTU {}", req.mtu());
                        read_buf = vec![0; req.mtu()];
                        reader_opt = Some(req.accept()?);
                    },
                    Some(CharacteristicControlEvent::Notify(notifier)) => {
                        println!("Accepting notify request event with MTU {}", notifier.mtu());
                        writer_opt = Some(notifier);
                    },
                    None => break,
                }
            },
            read_res = async {
                match &mut reader_opt {
                    Some(reader) if writer_opt.is_some() => reader.read(&mut read_buf).await,
                    _ => future::pending().await,
                }
            } => {
                match read_res {
                    Ok(0) => {
                        println!("Read stream ended");
                        reader_opt = None;
                    }
                    Ok(n) => {
                        let value = read_buf[..n].to_vec();
                        println!("Echoing {} bytes: {:x?} ... {:x?}", value.len(), &value[0..4.min(value.len())], &value[value.len().saturating_sub(4) ..]);
                        if value.len() < 512 {
                            println!();
                        }
                        if let Err(err) = writer_opt.as_mut().unwrap().write_all(&value).await {
                            println!("Write failed: {}", &err);
                            writer_opt = None;
                        }
                    }
                    Err(err) => {
                        println!("Read stream error: {}", &err);
                        reader_opt = None;
                    }
                }
            }
        }
    }

    println!("Removing service and advertisement");
    drop(app_handle);
    drop(adv_handle);
    sleep(Duration::from_secs(1)).await;

    Ok(())
}
examples/gatt_server_io.rs (line 97)
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
async fn main() -> bluer::Result<()> {
    env_logger::init();
    let session = bluer::Session::new().await?;
    let adapter = session.default_adapter().await?;
    adapter.set_powered(true).await?;

    println!("Advertising on Bluetooth adapter {} with address {}", adapter.name(), adapter.address().await?);
    let mut manufacturer_data = BTreeMap::new();
    manufacturer_data.insert(MANUFACTURER_ID, vec![0x21, 0x22, 0x23, 0x24]);
    let le_advertisement = Advertisement {
        service_uuids: vec![SERVICE_UUID].into_iter().collect(),
        manufacturer_data,
        discoverable: Some(true),
        local_name: Some("gatt_server".to_string()),
        ..Default::default()
    };
    let adv_handle = adapter.advertise(le_advertisement).await?;

    println!("Serving GATT service on Bluetooth adapter {}", adapter.name());
    let (service_control, service_handle) = service_control();
    let (char_control, char_handle) = characteristic_control();
    let app = Application {
        services: vec![Service {
            uuid: SERVICE_UUID,
            primary: true,
            characteristics: vec![Characteristic {
                uuid: CHARACTERISTIC_UUID,
                write: Some(CharacteristicWrite {
                    write: true,
                    write_without_response: true,
                    method: CharacteristicWriteMethod::Io,
                    ..Default::default()
                }),
                notify: Some(CharacteristicNotify {
                    notify: true,
                    method: CharacteristicNotifyMethod::Io,
                    ..Default::default()
                }),
                control_handle: char_handle,
                ..Default::default()
            }],
            control_handle: service_handle,
            ..Default::default()
        }],
        ..Default::default()
    };
    let app_handle = adapter.serve_gatt_application(app).await?;

    println!("Service handle is 0x{:x}", service_control.handle()?);
    println!("Characteristic handle is 0x{:x}", char_control.handle()?);

    println!("Service ready. Press enter to quit.");
    let stdin = BufReader::new(tokio::io::stdin());
    let mut lines = stdin.lines();

    let mut value: Vec<u8> = vec![0x10, 0x01, 0x01, 0x10];
    let mut read_buf = Vec::new();
    let mut reader_opt: Option<CharacteristicReader> = None;
    let mut writer_opt: Option<CharacteristicWriter> = None;
    let mut interval = interval(Duration::from_secs(1));
    pin_mut!(char_control);

    loop {
        tokio::select! {
            _ = lines.next_line() => break,
            evt = char_control.next() => {
                match evt {
                    Some(CharacteristicControlEvent::Write(req)) => {
                        println!("Accepting write event with MTU {} from {}", req.mtu(), req.device_address());
                        read_buf = vec![0; req.mtu()];
                        reader_opt = Some(req.accept()?);
                    },
                    Some(CharacteristicControlEvent::Notify(notifier)) => {
                        println!("Accepting notify request event with MTU {} from {}", notifier.mtu(), notifier.device_address());
                        writer_opt = Some(notifier);
                    },
                    None => break,
                }
            }
            _ = interval.tick() => {
                println!("Decrementing each element by one");
                for v in &mut *value {
                    *v = v.saturating_sub(1);
                }
                println!("Value is {:x?}", &value);
                if let Some(writer) = writer_opt.as_mut() {
                    println!("Notifying with value {:x?}", &value);
                    if let Err(err) = writer.write(&value).await {
                        println!("Notification stream error: {}", &err);
                        writer_opt = None;
                    }
                }
            }
            read_res = async {
                match &mut reader_opt {
                    Some(reader) => reader.read(&mut read_buf).await,
                    None => future::pending().await,
                }
            } => {
                match read_res {
                    Ok(0) => {
                        println!("Write stream ended");
                        reader_opt = None;
                    }
                    Ok(n) => {
                        value = read_buf[0..n].to_vec();
                        println!("Write request with {} bytes: {:x?}", n, &value);
                    }
                    Err(err) => {
                        println!("Write stream error: {}", &err);
                        reader_opt = None;
                    }
                }
            }
        }
    }

    println!("Removing service and advertisement");
    drop(app_handle);
    drop(adv_handle);
    sleep(Duration::from_secs(1)).await;

    Ok(())
}
source

pub async fn closed(&self) -> Result<()>

Waits for the remote device to stop the notification session.

source

pub fn is_closed(&self) -> Result<bool>

Checks if the remote device has stopped the notification session.

source

pub async fn sendable(&self) -> Result<()>

Waits for send space to become available.

source

pub fn try_send(&self, buf: &[u8]) -> Result<()>

Tries to send the characteristic value using a single write or notify operation.

The length of buf must not exceed Self::mtu.

Does not wait for send space to become available.

source

pub async fn send(&self, buf: &[u8]) -> Result<()>

Send the characteristic value using a single write or notify operation.

The length of buf must not exceed Self::mtu.

Waits for send space to become available.

source

pub fn into_raw_fd(self) -> Result<RawFd>

Consumes this object, returning the raw underlying file descriptor.

Trait Implementations§

source§

impl AsRawFd for CharacteristicWriter

source§

fn as_raw_fd(&self) -> RawFd

Extracts the raw file descriptor. Read more
source§

impl AsyncWrite for CharacteristicWriter

source§

fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8] ) -> Poll<Result<usize>>

Attempt to write bytes from buf into the characteristic value stream.

A single write operation will send no more than mtu bytes. However, attempting to send a larger buffer will not result in an error but a partial send.

source§

fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Attempts to flush the object, ensuring that any buffered data reach their destination. Read more
source§

fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>

Initiates or attempts to shut down this writer, returning success when the I/O connection has completely shut down. Read more
source§

fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>] ) -> Poll<Result<usize, Error>>

Like poll_write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

Determines if this writer has an efficient poll_write_vectored implementation. Read more
source§

impl Debug for CharacteristicWriter

source§

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

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

impl IntoRawFd for CharacteristicWriter

source§

fn into_raw_fd(self) -> RawFd

Consumes this object, returning the raw underlying file descriptor. Read more
source§

impl<'pin> Unpin for CharacteristicWriter
where __CharacteristicWriter<'pin>: Unpin,

Auto Trait Implementations§

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<W> AsyncWriteExt for W
where W: AsyncWrite + ?Sized,

source§

fn write<'a>(&'a mut self, src: &'a [u8]) -> Write<'a, Self>
where Self: Unpin,

Writes a buffer into this writer, returning how many bytes were written. Read more
source§

fn write_vectored<'a, 'b>( &'a mut self, bufs: &'a [IoSlice<'b>] ) -> WriteVectored<'a, 'b, Self>
where Self: Unpin,

Like write, except that it writes from a slice of buffers. Read more
source§

fn write_buf<'a, B>(&'a mut self, src: &'a mut B) -> WriteBuf<'a, Self, B>
where Self: Sized + Unpin, B: Buf,

Writes a buffer into this writer, advancing the buffer’s internal cursor. Read more
source§

fn write_all_buf<'a, B>( &'a mut self, src: &'a mut B ) -> WriteAllBuf<'a, Self, B>
where Self: Sized + Unpin, B: Buf,

Attempts to write an entire buffer into this writer. Read more
source§

fn write_all<'a>(&'a mut self, src: &'a [u8]) -> WriteAll<'a, Self>
where Self: Unpin,

Attempts to write an entire buffer into this writer. Read more
source§

fn write_u8(&mut self, n: u8) -> WriteU8<&mut Self>
where Self: Unpin,

Writes an unsigned 8-bit integer to the underlying writer. Read more
source§

fn write_i8(&mut self, n: i8) -> WriteI8<&mut Self>
where Self: Unpin,

Writes a signed 8-bit integer to the underlying writer. Read more
source§

fn write_u16(&mut self, n: u16) -> WriteU16<&mut Self>
where Self: Unpin,

Writes an unsigned 16-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i16(&mut self, n: i16) -> WriteI16<&mut Self>
where Self: Unpin,

Writes a signed 16-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u32(&mut self, n: u32) -> WriteU32<&mut Self>
where Self: Unpin,

Writes an unsigned 32-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i32(&mut self, n: i32) -> WriteI32<&mut Self>
where Self: Unpin,

Writes a signed 32-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u64(&mut self, n: u64) -> WriteU64<&mut Self>
where Self: Unpin,

Writes an unsigned 64-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i64(&mut self, n: i64) -> WriteI64<&mut Self>
where Self: Unpin,

Writes an signed 64-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_u128(&mut self, n: u128) -> WriteU128<&mut Self>
where Self: Unpin,

Writes an unsigned 128-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_i128(&mut self, n: i128) -> WriteI128<&mut Self>
where Self: Unpin,

Writes an signed 128-bit integer in big-endian order to the underlying writer. Read more
source§

fn write_f32(&mut self, n: f32) -> WriteF32<&mut Self>
where Self: Unpin,

Writes an 32-bit floating point type in big-endian order to the underlying writer. Read more
source§

fn write_f64(&mut self, n: f64) -> WriteF64<&mut Self>
where Self: Unpin,

Writes an 64-bit floating point type in big-endian order to the underlying writer. Read more
source§

fn write_u16_le(&mut self, n: u16) -> WriteU16Le<&mut Self>
where Self: Unpin,

Writes an unsigned 16-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i16_le(&mut self, n: i16) -> WriteI16Le<&mut Self>
where Self: Unpin,

Writes a signed 16-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u32_le(&mut self, n: u32) -> WriteU32Le<&mut Self>
where Self: Unpin,

Writes an unsigned 32-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i32_le(&mut self, n: i32) -> WriteI32Le<&mut Self>
where Self: Unpin,

Writes a signed 32-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u64_le(&mut self, n: u64) -> WriteU64Le<&mut Self>
where Self: Unpin,

Writes an unsigned 64-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i64_le(&mut self, n: i64) -> WriteI64Le<&mut Self>
where Self: Unpin,

Writes an signed 64-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_u128_le(&mut self, n: u128) -> WriteU128Le<&mut Self>
where Self: Unpin,

Writes an unsigned 128-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_i128_le(&mut self, n: i128) -> WriteI128Le<&mut Self>
where Self: Unpin,

Writes an signed 128-bit integer in little-endian order to the underlying writer. Read more
source§

fn write_f32_le(&mut self, n: f32) -> WriteF32Le<&mut Self>
where Self: Unpin,

Writes an 32-bit floating point type in little-endian order to the underlying writer. Read more
source§

fn write_f64_le(&mut self, n: f64) -> WriteF64Le<&mut Self>
where Self: Unpin,

Writes an 64-bit floating point type in little-endian order to the underlying writer. Read more
source§

fn flush(&mut self) -> Flush<'_, Self>
where Self: Unpin,

Flushes this output stream, ensuring that all intermediately buffered contents reach their destination. Read more
source§

fn shutdown(&mut self) -> Shutdown<'_, Self>
where Self: Unpin,

Shuts down the output stream, ensuring that the value can be dropped cleanly. 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> 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, U> TryFrom<U> for T
where U: Into<T>,

§

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>,

§

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.