Actually use the async networking

This commit is contained in:
Garen Tyler 2021-03-01 21:13:02 -07:00
parent a4b461b6c0
commit 03405dfb79
5 changed files with 77 additions and 67 deletions

View File

@ -3,12 +3,12 @@
pub use functions::*; pub use functions::*;
pub use numbers::*; pub use numbers::*;
pub use other::*; pub use other::*;
use std::io::prelude::*; use tokio::io::{AsyncReadExt, AsyncWriteExt};
use std::net::TcpStream; use tokio::net::TcpStream;
// /// Make sure all types can serialize and deserialize to/from `Vec<u8>`. // /// Make sure all types can serialize and deserialize to/from `Vec<u8>`.
// pub trait MCType: Into<Vec<u8>> + TryFrom<Vec<u8>> + Display { // pub trait MCType: Into<Vec<u8>> + TryFrom<Vec<u8>> + Display {
// pub async fn read(_stream: &mut TcpStream) -> std::io::Result<Self>; // pub async fn read(_stream: &mut TcpStream) -> tokio::io::Result<Self>;
// } // }
/// Helper functions. /// Helper functions.
@ -16,14 +16,14 @@ pub mod functions {
use super::*; use super::*;
/// Read a single byte from the given `TcpStream`. /// Read a single byte from the given `TcpStream`.
pub async fn read_byte(t: &mut TcpStream) -> std::io::Result<u8> { pub async fn read_byte(t: &mut TcpStream) -> tokio::io::Result<u8> {
let mut buffer = [0u8; 1]; let mut buffer = [0u8; 1];
t.read_exact(&mut buffer)?; t.read_exact(&mut buffer).await?;
Ok(buffer[0]) Ok(buffer[0])
} }
/// Write a single byte to the given `TcpStream`. /// Write a single byte to the given `TcpStream`.
pub fn write_byte(t: &mut TcpStream, value: u8) -> std::io::Result<u8> { pub async fn write_byte(t: &mut TcpStream, value: u8) -> tokio::io::Result<u8> {
t.write(&[value])?; t.write(&[value]).await?;
Ok(value) Ok(value)
} }
/// Take `l` bytes from the given `Vec<u8>`. /// Take `l` bytes from the given `Vec<u8>`.
@ -43,8 +43,8 @@ pub mod functions {
a.into_boxed_slice() a.into_boxed_slice()
} }
/// Makes returning errors shorter. /// Makes returning errors shorter.
pub fn io_error(s: &str) -> std::io::Error { pub fn io_error(s: &str) -> tokio::io::Error {
use std::io::{Error, ErrorKind}; use tokio::io::{Error, ErrorKind};
Error::new(ErrorKind::Other, s) Error::new(ErrorKind::Other, s)
} }
} }
@ -113,7 +113,7 @@ pub mod other {
} }
} }
impl MCBoolean { impl MCBoolean {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCBoolean> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCBoolean> {
let b = read_byte(t).await?; let b = read_byte(t).await?;
Ok(MCBoolean::try_from(vec![b]).unwrap()) Ok(MCBoolean::try_from(vec![b]).unwrap())
} }
@ -188,7 +188,7 @@ pub mod other {
} }
} }
impl MCString { impl MCString {
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let str_len = MCVarInt::read(t).await?; let str_len = MCVarInt::read(t).await?;
let mut str_bytes = vec![]; let mut str_bytes = vec![];
for _ in 0..str_len.into() { for _ in 0..str_len.into() {
@ -243,7 +243,7 @@ pub mod other {
} }
} }
impl MCChat { impl MCChat {
pub async fn read(_t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(_t: &mut TcpStream) -> tokio::io::Result<Self> {
Err(io_error("Cannot read MCChat from stream")) Err(io_error("Cannot read MCChat from stream"))
} }
} }
@ -261,7 +261,7 @@ pub mod numbers {
pub value: i8, // -128 to 127 pub value: i8, // -128 to 127
} }
impl MCByte { impl MCByte {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCByte> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCByte> {
Ok(MCByte::from_bytes(vec![read_byte(t).await?])) Ok(MCByte::from_bytes(vec![read_byte(t).await?]))
} }
pub fn from_bytes(v: Vec<u8>) -> MCByte { pub fn from_bytes(v: Vec<u8>) -> MCByte {
@ -319,7 +319,7 @@ pub mod numbers {
pub value: u8, // 0 to 255 pub value: u8, // 0 to 255
} }
impl MCUnsignedByte { impl MCUnsignedByte {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCUnsignedByte> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCUnsignedByte> {
Ok(MCUnsignedByte::from_bytes(vec![read_byte(t).await?])) Ok(MCUnsignedByte::from_bytes(vec![read_byte(t).await?]))
} }
pub fn from_bytes(v: Vec<u8>) -> MCUnsignedByte { pub fn from_bytes(v: Vec<u8>) -> MCUnsignedByte {
@ -377,7 +377,7 @@ pub mod numbers {
pub value: i16, // -32768 to 32767 pub value: i16, // -32768 to 32767
} }
impl MCShort { impl MCShort {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCShort> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCShort> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
bytes.push(read_byte(t).await?); // MSD bytes.push(read_byte(t).await?); // MSD
bytes.push(read_byte(t).await?); // LSD bytes.push(read_byte(t).await?); // LSD
@ -440,7 +440,7 @@ pub mod numbers {
pub value: u16, // 0 to 65535 pub value: u16, // 0 to 65535
} }
impl MCUnsignedShort { impl MCUnsignedShort {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCUnsignedShort> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCUnsignedShort> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
bytes.push(read_byte(t).await?); // MSD bytes.push(read_byte(t).await?); // MSD
bytes.push(read_byte(t).await?); // LSD bytes.push(read_byte(t).await?); // LSD
@ -503,7 +503,7 @@ pub mod numbers {
pub value: i32, // -2147483648 to 2147483647 pub value: i32, // -2147483648 to 2147483647
} }
impl MCInt { impl MCInt {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCInt> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCInt> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..4 { for _ in 0..4 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -567,7 +567,7 @@ pub mod numbers {
pub value: u32, // 0 to 4294967295 pub value: u32, // 0 to 4294967295
} }
impl MCUnsignedInt { impl MCUnsignedInt {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCUnsignedInt> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCUnsignedInt> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..4 { for _ in 0..4 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -631,7 +631,7 @@ pub mod numbers {
pub value: i64, // -9223372036854775808 to 9223372036854775807 pub value: i64, // -9223372036854775808 to 9223372036854775807
} }
impl MCLong { impl MCLong {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCLong> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCLong> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..8 { for _ in 0..8 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -695,7 +695,7 @@ pub mod numbers {
pub value: u64, // 0 to 18446744073709551615 pub value: u64, // 0 to 18446744073709551615
} }
impl MCUnsignedLong { impl MCUnsignedLong {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCUnsignedLong> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCUnsignedLong> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..8 { for _ in 0..8 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -759,7 +759,7 @@ pub mod numbers {
pub value: f32, // 32-bit floating point number pub value: f32, // 32-bit floating point number
} }
impl MCFloat { impl MCFloat {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCFloat> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCFloat> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..4 { for _ in 0..4 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -823,7 +823,7 @@ pub mod numbers {
pub value: f64, // 64-bit floating point number pub value: f64, // 64-bit floating point number
} }
impl MCDouble { impl MCDouble {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCDouble> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCDouble> {
let mut bytes = Vec::new(); let mut bytes = Vec::new();
for _ in 0..8 { for _ in 0..8 {
bytes.push(read_byte(t).await?); bytes.push(read_byte(t).await?);
@ -887,7 +887,7 @@ pub mod numbers {
pub value: i32, // Variable length 32-bit integer pub value: i32, // Variable length 32-bit integer
} }
impl MCVarInt { impl MCVarInt {
pub async fn read(t: &mut TcpStream) -> std::io::Result<MCVarInt> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<MCVarInt> {
let mut num_read = 0; let mut num_read = 0;
let mut result = 0i32; let mut result = 0i32;
let mut read = 0u8; let mut read = 0u8;

View File

@ -5,8 +5,8 @@ use crate::mctypes::*;
use log::{debug, info}; use log::{debug, info};
use packets::*; use packets::*;
use serde_json::json; use serde_json::json;
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::sync::mpsc::{self, Receiver, TryRecvError}; use std::sync::mpsc::{self, Receiver, TryRecvError};
use tokio::net::{TcpListener, TcpStream, ToSocketAddrs};
/// The part of the server that handles /// The part of the server that handles
/// connecting clients and receiving/sending packets. /// connecting clients and receiving/sending packets.
@ -20,18 +20,24 @@ impl NetworkServer {
/// then hold that in a queue for processing on an update. /// then hold that in a queue for processing on an update.
pub fn new<A: 'static + ToSocketAddrs + Send>(addr: A) -> NetworkServer { pub fn new<A: 'static + ToSocketAddrs + Send>(addr: A) -> NetworkServer {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
std::thread::spawn(move || { tokio::task::spawn(async move {
let listener = TcpListener::bind(addr).expect("Could not bind to TCP socket"); let listener = TcpListener::bind(addr)
for (id, stream) in listener.incoming().enumerate() { .await
if let Ok(s) = stream { .expect("Could not bind to TCP socket");
tx.send(NetworkClient { let mut id = 0;
id: id as u128, loop {
connected: true, let (stream, _) = listener
stream: s, .accept()
state: NetworkClientState::Handshake, .await
})
.expect("Network receiver disconnected"); .expect("Network receiver disconnected");
} tx.send(NetworkClient {
id: id as u128,
connected: true,
stream,
state: NetworkClientState::Handshake,
})
.expect("Network receiver disconnected");
id += 1;
} }
}); });
info!("Network server started!"); info!("Network server started!");
@ -87,7 +93,8 @@ impl NetworkClient {
pub async fn update(&mut self) { pub async fn update(&mut self) {
match self.state { match self.state {
NetworkClientState::Handshake => { NetworkClientState::Handshake => {
let (_packet_length, _packet_id) = read_packet_header(&mut self.stream).await.unwrap(); let (_packet_length, _packet_id) =
read_packet_header(&mut self.stream).await.unwrap();
let handshake = Handshake::read(&mut self.stream).await.unwrap(); let handshake = Handshake::read(&mut self.stream).await.unwrap();
// Minecraft versions 1.8 - 1.8.9 use protocol version 47. // Minecraft versions 1.8 - 1.8.9 use protocol version 47.
let compatible_versions = handshake.protocol_version == 47; let compatible_versions = handshake.protocol_version == 47;
@ -109,7 +116,8 @@ impl NetworkClient {
debug!("Got handshake: {:?}", handshake); debug!("Got handshake: {:?}", handshake);
} }
NetworkClientState::Status => { NetworkClientState::Status => {
let (_packet_length, _packet_id) = read_packet_header(&mut self.stream).await.unwrap(); let (_packet_length, _packet_id) =
read_packet_header(&mut self.stream).await.unwrap();
let statusrequest = StatusRequest::read(&mut self.stream).await.unwrap(); let statusrequest = StatusRequest::read(&mut self.stream).await.unwrap();
debug!("Got status request: {:?}", statusrequest); debug!("Got status request: {:?}", statusrequest);
let mut statusresponse = StatusResponse::new(); let mut statusresponse = StatusResponse::new();
@ -138,7 +146,8 @@ impl NetworkClient {
.into(); .into();
statusresponse.write(&mut self.stream).await.unwrap(); statusresponse.write(&mut self.stream).await.unwrap();
debug!("Sending status response: StatusResponse"); debug!("Sending status response: StatusResponse");
let (_packet_length, _packet_id) = read_packet_header(&mut self.stream).await.unwrap(); let (_packet_length, _packet_id) =
read_packet_header(&mut self.stream).await.unwrap();
let statusping = StatusPing::read(&mut self.stream).await.unwrap(); let statusping = StatusPing::read(&mut self.stream).await.unwrap();
debug!("Got status ping: {:?}", statusping); debug!("Got status ping: {:?}", statusping);
let mut statuspong = StatusPong::new(); let mut statuspong = StatusPong::new();
@ -148,7 +157,8 @@ impl NetworkClient {
self.state = NetworkClientState::Disconnected; self.state = NetworkClientState::Disconnected;
} }
NetworkClientState::Login => { NetworkClientState::Login => {
let (_packet_length, _packet_id) = read_packet_header(&mut self.stream).await.unwrap(); let (_packet_length, _packet_id) =
read_packet_header(&mut self.stream).await.unwrap();
let loginstart = LoginStart::read(&mut self.stream).await.unwrap(); let loginstart = LoginStart::read(&mut self.stream).await.unwrap();
debug!("{:?}", loginstart); debug!("{:?}", loginstart);
// Offline mode skips encryption and compression. // Offline mode skips encryption and compression.

View File

@ -1,6 +1,6 @@
use crate::mctypes::*; use crate::mctypes::*;
use std::convert::{Into, TryFrom}; use std::convert::{Into, TryFrom};
use std::net::TcpStream; use tokio::net::TcpStream;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct StatusResponse { pub struct StatusResponse {
@ -28,14 +28,14 @@ impl StatusResponse {
json_response: MCString::from(""), json_response: MCString::from(""),
} }
} }
pub async fn read(t: &'_ mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &'_ mut TcpStream) -> tokio::io::Result<Self> {
let mut statusresponse = StatusResponse::new(); let mut statusresponse = StatusResponse::new();
statusresponse.json_response = MCString::read(t).await?; statusresponse.json_response = MCString::read(t).await?;
Ok(statusresponse) Ok(statusresponse)
} }
pub async fn write(&self, t: &'_ mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &'_ mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -65,14 +65,14 @@ impl StatusPong {
pub fn new() -> Self { pub fn new() -> Self {
StatusPong { payload: 0.into() } StatusPong { payload: 0.into() }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut statuspong = StatusPong::new(); let mut statuspong = StatusPong::new();
statuspong.payload = MCLong::read(t).await?; statuspong.payload = MCLong::read(t).await?;
Ok(statuspong) Ok(statuspong)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -107,15 +107,15 @@ impl LoginSuccess {
username: MCString::from(""), username: MCString::from(""),
} }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut loginsuccess = LoginSuccess::new(); let mut loginsuccess = LoginSuccess::new();
loginsuccess.uuid = MCString::read(t).await?; loginsuccess.uuid = MCString::read(t).await?;
loginsuccess.username = MCString::read(t).await?; loginsuccess.username = MCString::read(t).await?;
Ok(loginsuccess) Ok(loginsuccess)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -149,16 +149,16 @@ impl LoginDisconnect {
}, },
} }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut logindisconnect = LoginDisconnect::new(); let mut logindisconnect = LoginDisconnect::new();
logindisconnect.reason = MCChat { logindisconnect.reason = MCChat {
text: MCString::read(t).await?, text: MCString::read(t).await?,
}; };
Ok(logindisconnect) Ok(logindisconnect)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }

View File

@ -6,10 +6,10 @@ pub mod serverbound;
use crate::mctypes::MCVarInt; use crate::mctypes::MCVarInt;
pub use clientbound::*; pub use clientbound::*;
pub use serverbound::*; pub use serverbound::*;
use std::net::TcpStream; use tokio::net::TcpStream;
/// A helper function to read the packet header. /// A helper function to read the packet header.
pub async fn read_packet_header(t: &mut TcpStream) -> std::io::Result<(MCVarInt, MCVarInt)> { pub async fn read_packet_header(t: &mut TcpStream) -> tokio::io::Result<(MCVarInt, MCVarInt)> {
let length = MCVarInt::read(t).await?; let length = MCVarInt::read(t).await?;
let id = MCVarInt::read(t).await?; let id = MCVarInt::read(t).await?;
Ok((length, id)) Ok((length, id))

View File

@ -1,6 +1,6 @@
use crate::mctypes::*; use crate::mctypes::*;
use std::convert::{Into, TryFrom}; use std::convert::{Into, TryFrom};
use std::net::TcpStream; use tokio::net::TcpStream;
/// Needed for every interaction with the server. /// Needed for every interaction with the server.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -38,7 +38,7 @@ impl Handshake {
next_state: 0.into(), next_state: 0.into(),
} }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut handshake = Handshake::new(); let mut handshake = Handshake::new();
handshake.protocol_version = MCVarInt::read(t).await?; handshake.protocol_version = MCVarInt::read(t).await?;
handshake.server_address = MCString::read(t).await?; handshake.server_address = MCString::read(t).await?;
@ -46,9 +46,9 @@ impl Handshake {
handshake.next_state = MCVarInt::read(t).await?; handshake.next_state = MCVarInt::read(t).await?;
Ok(handshake) Ok(handshake)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -75,13 +75,13 @@ impl StatusRequest {
pub fn new() -> Self { pub fn new() -> Self {
StatusRequest {} StatusRequest {}
} }
pub async fn read(_t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(_t: &mut TcpStream) -> tokio::io::Result<Self> {
let statusrequest = StatusRequest::new(); let statusrequest = StatusRequest::new();
Ok(statusrequest) Ok(statusrequest)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -111,14 +111,14 @@ impl StatusPing {
pub fn new() -> Self { pub fn new() -> Self {
StatusPing { payload: 0.into() } StatusPing { payload: 0.into() }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut statusping = StatusPing::new(); let mut statusping = StatusPing::new();
statusping.payload = MCLong::read(t).await?; statusping.payload = MCLong::read(t).await?;
Ok(statusping) Ok(statusping)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }
@ -150,14 +150,14 @@ impl LoginStart {
player_name: "".into(), player_name: "".into(),
} }
} }
pub async fn read(t: &mut TcpStream) -> std::io::Result<Self> { pub async fn read(t: &mut TcpStream) -> tokio::io::Result<Self> {
let mut loginstart = LoginStart::new(); let mut loginstart = LoginStart::new();
loginstart.player_name = MCString::read(t).await?; loginstart.player_name = MCString::read(t).await?;
Ok(loginstart) Ok(loginstart)
} }
pub async fn write(&self, t: &mut TcpStream) -> std::io::Result<()> { pub async fn write(&self, t: &mut TcpStream) -> tokio::io::Result<()> {
for b in Into::<Vec<u8>>::into(self.clone()) { for b in Into::<Vec<u8>>::into(self.clone()) {
write_byte(t, b)?; write_byte(t, b).await?;
} }
Ok(()) Ok(())
} }