Skip to content

Commit

Permalink
Device: various fixes & improvements (#277)
Browse files Browse the repository at this point in the history
* various fixes & improvements

* fmt

* fix path

* fix path

* fix fmt check suggestions
  • Loading branch information
boozook authored Apr 9, 2024
1 parent 5844185 commit d03286d
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 88 deletions.
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ jobs:
run: cargo fmt --all

- name: Suggest Changes
continue-on-error: true
if: success() && (github.event_name == 'pull_request' || github.event_name == 'pull_request_target')
# https://docs.github.com/en/rest/pulls/reviews?apiVersion=2022-11-28#create-a-review-for-a-pull-request
uses: parkerbxyz/suggest-changes@v1
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion cargo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cargo-playdate"
version = "0.4.0-beta.2"
version = "0.4.0-beta.3"
readme = "README.md"
description = "Build tool for neat yellow console."
keywords = ["playdate", "build", "cargo", "plugin", "cargo-subcommand"]
Expand Down Expand Up @@ -93,3 +93,7 @@ rand = "0.8"

[target.'cfg(unix)'.dev-dependencies]
nix = { version = "0.28", features = ["signal"] }


[features]
eject = ["device/eject"] # windows only, enable one more unmount method
2 changes: 1 addition & 1 deletion cargo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ fn execute(config: &Config) -> CargoResult<()> {
.map(|m| m.device.value.as_ref())
.flatten()
{
format!("on the '{}'", query.to_printable_string()).into()
format!("on the '{}'", query.to_value_string()).into()
} else {
"on a device".into()
}
Expand Down
2 changes: 1 addition & 1 deletion support/device/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "playdate-device"
version = "0.2.2"
version = "0.2.3"
readme = "README.md"
description = "Cross-platform interface Playdate device, async & blocking."
keywords = ["playdate", "usb", "serial"]
Expand Down
2 changes: 1 addition & 1 deletion support/device/src/device/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub async fn wait_mode_change(mut dev: Device, to: Mode, retry: Retries<impl Ite
);

if mode == to {
dev.info().serial_number().map(|s| trace!("{s} is in {to} mode."));
trace!("{dev} is in {to} mode.");
return Ok(dev);
}

Expand Down
53 changes: 42 additions & 11 deletions support/device/src/device/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::path::PathBuf;
use std::str::FromStr;

use super::serial::SerialNumber;
use self::error::DeviceQueryError as Error;


pub const DEVICE_SERIAL_ENV: &str = "PLAYDATE_SERIAL_DEVICE";
Expand Down Expand Up @@ -76,26 +77,20 @@ pub enum Value {
Com(u16),
}

type ParseError = <SerialNumber as FromStr>::Err;
impl FromStr for Value {
type Err = crate::error::Error;
type Err = Error;

fn from_str(dev: &str) -> Result<Self, Self::Err> {
let name = dev.trim();
if name.is_empty() {
return Err(ParseError::from(name).into());
return Err(error::ParseError::from(name).into());
}

#[cfg(windows)]
match name.strip_prefix("COM").map(|s| s.parse::<u16>()) {
Some(Ok(com)) => return Ok(Value::Com(com)),
Some(Err(err)) => {
use std::io::{Error, ErrorKind};

return Err(Error::new(
ErrorKind::InvalidInput,
format!("Invalid format, seems to COM port, but {err}."),
).into());
return Err(Error::invalid(format!("Invalid format, seems to COM port, but {err}.")));
},
None => { /* nothing there */ },
}
Expand Down Expand Up @@ -124,16 +119,52 @@ impl FromStr for Value {
}

impl<'s> TryFrom<&'s str> for Value {
type Error = crate::error::Error;
type Error = Error;
fn try_from(dev: &'s str) -> Result<Self, Self::Error> { Self::from_str(dev) }
}

impl Value {
pub fn to_printable_string(&self) -> String {
pub fn to_value_string(&self) -> String {
match self {
Self::Serial(sn) => sn.to_string(),
Self::Path(p) => p.display().to_string(),
Self::Com(n) => format!("COM{n}"),
}
}
}


pub mod error {
use std::backtrace::Backtrace;
use std::str::FromStr;
use thiserror::Error;
use miette::Diagnostic;

pub type ParseError = <super::SerialNumber as FromStr>::Err;


#[derive(Error, Debug, Diagnostic)]
pub enum DeviceQueryError {
#[error(transparent)]
#[diagnostic(transparent)]
DeviceSerial {
#[backtrace]
#[from]
source: ParseError,
},

#[error("Invalid query format: {message}")]
Invalid {
message: String,
#[backtrace]
backtrace: Backtrace,
},
}

impl DeviceQueryError {
pub fn invalid(message: String) -> Self {
Self::Invalid { message,
backtrace: Backtrace::capture() }
}
}
}
47 changes: 25 additions & 22 deletions support/device/src/device/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ impl SerialNumber {
}

impl FromStr for SerialNumber {
type Err = DeviceSerialFormatError;
type Err = error::SerialNumberFormatError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::contained_in(s).ok_or_else(|| DeviceSerialFormatError::from(s))
Self::contained_in(s).ok_or_else(|| error::SerialNumberFormatError::from(s))
}
}

Expand Down Expand Up @@ -82,30 +82,33 @@ impl std::fmt::Display for SerialNumber {
}


use std::backtrace::Backtrace;
use thiserror::Error;
use miette::Diagnostic;
pub mod error {

use std::backtrace::Backtrace;
use thiserror::Error;
use miette::Diagnostic;

#[derive(Error, Debug, Diagnostic)]
#[error("Invalid serial number: {value}, expected format: PDUN-XNNNNNN.")]
pub struct DeviceSerialFormatError {
pub value: String,
#[backtrace]
backtrace: Backtrace,
}

impl DeviceSerialFormatError {
fn new(value: String) -> Self {
Self { value,
backtrace: Backtrace::capture() }
#[derive(Error, Debug, Diagnostic)]
#[error("invalid serial number `{value}`, expected format `PDUN-XNNNNNN`.")]
pub struct SerialNumberFormatError {
pub value: String,
#[backtrace]
backtrace: Backtrace,
}
}

impl From<String> for DeviceSerialFormatError {
fn from(value: String) -> Self { Self::new(value) }
}
impl SerialNumberFormatError {
fn new(value: String) -> Self {
Self { value,
backtrace: Backtrace::capture() }
}
}

impl From<String> for SerialNumberFormatError {
fn from(value: String) -> Self { Self::new(value) }
}

impl From<&str> for DeviceSerialFormatError {
fn from(value: &str) -> Self { Self::new(value.to_owned()) }
impl From<&str> for SerialNumberFormatError {
fn from(value: &str) -> Self { Self::new(value.to_owned()) }
}
}
2 changes: 1 addition & 1 deletion support/device/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub enum Error {
DeviceSerial {
#[backtrace]
#[from]
source: crate::device::serial::DeviceSerialFormatError,
source: crate::device::serial::error::SerialNumberFormatError,
},

#[error(transparent)]
Expand Down
33 changes: 1 addition & 32 deletions support/device/src/interface/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use crate::error::Error;


pub trait Out: In {
// type Error: std::error::Error;

fn send(&self, data: &[u8]) -> impl Future<Output = Result<usize, Error>>;

fn send_cmd(&self, cmd: Command) -> impl Future<Output = Result<usize, Error>> {
Expand All @@ -27,36 +25,7 @@ pub trait Out: In {
}
}

pub trait In {
// type Error: std::error::Error = crate::error::Error;
}
pub trait In {}

pub trait Interface: Out {}
impl<T: In + Out> Interface for T {}


// pub trait AsyncSend {
// fn send_cmd(&mut self,
// cmd: crate::device::command::Command)
// -> impl std::future::Future<Output = Result<usize, Error>>;
// }


// mod ext {
// use super::*;


// impl<T> AsyncSend for T
// where T: tokio::io::AsyncWriteExt,
// Self: Unpin
// {
// #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))]
// async fn send_cmd(&mut self, cmd: crate::device::command::Command) -> Result<usize, Error> {
// let cmd = cmd.with_break();
// let bytes = cmd.as_bytes();
// self.write_all(bytes).await?;
// self.flush().await?;
// Ok(bytes.len())
// }
// }
// }
7 changes: 1 addition & 6 deletions support/device/src/interface/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ use crate::device::command::Command;
use crate::error::Error;

pub trait Out: In {
// type Error: std::error::Error = crate::error::Error;

// fn send(&self, data: &[u8]) -> Result<usize, Self::Error>;
fn send_cmd(&self, cmd: Command) -> Result<usize, Error>;
}

pub trait In {
// type Error: std::error::Error = crate::error::Error;
}
pub trait In {}

pub trait Interface: In + Out {}
// impl<T: In<Error = Err> + Out<Error = Err>, Err> Interface for T {}
Expand Down
5 changes: 1 addition & 4 deletions support/device/src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ impl r#async::In for Interface
where crate::usb::Interface: r#async::In,
crate::serial::Interface: r#async::In
{
// type Error = Error;
}


Expand All @@ -79,6 +78,4 @@ impl blocking::Out for Interface {
}
}

impl blocking::In for Interface {
// type Error = crate::error::Error;
}
impl blocking::In for Interface {}
12 changes: 10 additions & 2 deletions support/device/src/mount/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ async fn wait_mount_point<T>(dev: Device, retry: Retries<T>) -> Result<MountedDe


#[cfg_attr(feature = "tracing", tracing::instrument())]
pub async fn unmount(query: Query) -> Result<Unordered<impl Future<Output = (Device, Result)>>> {
pub async fn unmount(query: Query) -> Result<impl Stream<Item = (Device, Result)>> {
match query.value {
Some(QueryValue::Path(path)) => {
// TODO: Check query is path and this is mounted volume.
Expand All @@ -324,7 +324,15 @@ pub async fn unmount(query: Query) -> Result<Unordered<impl Future<Output = (Dev
Some(QueryValue::Com(_)) => todo!("ERROR: not supported (impossible)"),
Some(QueryValue::Serial(sn)) => unmount_mb_sn(Some(sn)),
_ => unmount_mb_sn(None),
}.await
}.map_ok(|stream| {
stream.inspect(|(dev, res)| {
if let Some(err) = res.as_ref().err() {
error!("{dev}: {err}");
warn!("Please press 'A' on the Playdate to exit Data Disk mode.");
}
})
})
.await
}

/// Unmount device(s), then wait for state change to [`Data`][usb::mode::Mode::Data].
Expand Down
3 changes: 0 additions & 3 deletions support/device/src/mount/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ mod methods;
pub use methods::*;


// TODO: If unmount fails, do warn!("Please press 'A' on the Playdate to exit Data Disk mode.")


// TODO: MountError for this module


Expand Down
2 changes: 1 addition & 1 deletion support/device/src/mount/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub async fn volume_for(dev: &Device) -> Result<Volume, Error> {
}

let sn = dev.info().serial_number().ok_or_else(|| {
Error::DeviceSerial { source: crate::device::serial::DeviceSerialFormatError::from("missed") }
Error::DeviceSerial { source: crate::device::serial::error::SerialNumberFormatError::from("missed sn") }
})?;
let sn = SerialNumber::try_from(sn)?;
let dev_addr = dev.info().device_address() as u32;
Expand Down
25 changes: 25 additions & 0 deletions support/device/src/retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,28 @@ impl IterTime for Duration {
calc_interval(total_wait, self)
}
}


pub fn retry_blocking<F, R, E>(retry: Retries<impl IterTime>, f: F) -> Result<R, crate::error::Error>
where F: Fn() -> Result<R, E>,
E: Into<crate::error::Error> {
let total = &retry.total;
let iteration = retry.iters.interval(total);
let retries_num = total.as_millis() / iteration.as_millis();
trace!("start retries: {retries_num} * {iteration:?} ≈ {total:?}.");

let mut counter = retries_num;
loop {
trace!("try: {}/{retries_num}", retries_num - counter);
match f() {
Ok(r) => return Ok(r),
Err(e) => {
counter -= 1;
if counter == 0 {
return Err(e.into());
}
std::thread::sleep(iteration);
},
}
}
}

0 comments on commit d03286d

Please sign in to comment.