Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions flutter_package/example/native/hub/src/testing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ pub async fn run_unit_tests() {
let complex_signals = get_complex_signals();
for sent in complex_signals {
sent.clone().send_signal_to_dart();
let Some(signal_pack) = signal_receiver.recv().await else {
continue;
let signal_pack = match signal_receiver.recv().await {
Some(inner) => inner,
None => continue,
};
let received = signal_pack.message;
ComplexSignalTestResult(sent == received).send_signal_to_dart();
Expand Down
3 changes: 3 additions & 0 deletions flutter_package/lib/src/structure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ class RustSignalPack<T> {
/// without the overhead of serialization/deserialization.
final Uint8List binary;

/// Constructs a packed data transfer object that includes
/// the message and the binary data from Rust.
/// This constructor is not intended for external use outside the library.
RustSignalPack(this.message, this.binary);
}
29 changes: 16 additions & 13 deletions rust_crate/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ impl<T> SignalSender<T> {
pub fn send(&self, msg: T) {
let mut guard = self.inner.lock().recover();

// Enqueue the message
// Enqueue the message.
guard.queue.push_back(msg);
// Wake up the previous receiver making it receive `None`, if any
// Wake up the previous receiver making it receive `None`, if any.
if let Some(waker) = guard.waker.take() {
waker.wake();
}
Expand Down Expand Up @@ -96,21 +96,24 @@ impl<T> Future for RecvFuture<T> {
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut guard = self.inner.lock().recover();

// Only allow the current active receiver to receive messages
// Only allow the current active receiver to receive messages.
if guard.active_receiver_id == self.receiver_id {
if let Some(msg) = guard.queue.pop_front() {
// Check if more messages are in the queue
if !guard.queue.is_empty() {
// If so, wake the current task immediately
cx.waker().wake_by_ref();
match guard.queue.pop_front() {
Some(msg) => {
// Check if more messages are in the queue.
if !guard.queue.is_empty() {
// If so, wake the current task immediately.
cx.waker().wake_by_ref();
}
Poll::Ready(Some(msg))
}
None => {
guard.waker = Some(cx.waker().to_owned());
Poll::Pending
}
Poll::Ready(Some(msg))
} else {
guard.waker = Some(cx.waker().to_owned());
Poll::Pending
}
} else {
// Return None if this receiver is not the current active one
// Return None if this receiver is not the current active one.
Poll::Ready(None)
}
}
Expand Down
7 changes: 4 additions & 3 deletions rust_crate_cli/src/tool/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn run_command() -> Result<(), SetupError> {
// Check if the current directory is Flutter app's root.
let root_dir = current_dir()?;
if !is_flutter_app_project(&root_dir) {
Err(SetupError::NotFlutterApp)?;
return Err(SetupError::NotFlutterApp);
}

// Run a command from user input.
Expand Down Expand Up @@ -92,10 +92,11 @@ pub fn run_command() -> Result<(), SetupError> {

fn is_flutter_app_project(root_dir: &Path) -> bool {
let spec_file = root_dir.join("pubspec.yaml");
let Some(publish_to) = read_publish_to(&spec_file) else {
let publish_to = match read_publish_to(&spec_file) {
Some(inner) => inner,
// If the field is not readable,
// just treat this directory as a Flutter app project.
return true;
None => return true,
};
publish_to == "none"
}
112 changes: 54 additions & 58 deletions rust_crate_cli/src/tool/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ fn extract_signal_attributes(
}
attr
.parse_nested_meta(|meta| {
let Some(last_segment) = meta.path.segments.last() else {
return Err(syn::Error::new(
meta.path.span(),
"Missing derive item name",
));
let last_segment = match meta.path.segments.last() {
Some(inner) => inner,
None => {
return Err(syn::Error::new(
meta.path.span(),
"Missing derive item name",
));
}
};
let ident: &str = &last_segment.ident.to_string();
let signal_attr_op = match ident {
Expand Down Expand Up @@ -95,63 +98,56 @@ fn to_type_format(ty: &Type) -> Format {
Type::Path(TypePath { path, .. }) => {
// Get last segment
// (e.g., for `std::collections::BTreeMap`, get `BTreeMap`).
if let Some(last_segment) = path.segments.last() {
let ident = last_segment.ident.to_string();

match ident.as_str() {
"u8" => Format::U8,
"u16" => Format::U16,
"u32" => Format::U32,
"u64" => Format::U64,
"u128" => Format::U128,
"i8" => Format::I8,
"i16" => Format::I16,
"i32" => Format::I32,
"i64" => Format::I64,
"i128" => Format::I128,
"f32" => Format::F32,
"f64" => Format::F64,
"bool" => Format::Bool,
"char" => Format::Char,
"String" => Format::Str,
"Box" => {
if let Some(inner) = extract_generic(last_segment) {
to_type_format(&inner)
} else {
Format::unknown()
}
}
"Option" => {
if let Some(inner) = extract_generic(last_segment) {
Format::Option(Box::new(to_type_format(&inner)))
} else {
Format::unknown()
}
}
"Vec" | "HashSet" | "BTreeSet" => {
if let Some(inner) = extract_generic(last_segment) {
Format::Seq(Box::new(to_type_format(&inner)))
} else {
Format::unknown()
match path.segments.last() {
Some(last_segment) => {
let ident = last_segment.ident.to_string();
match ident.as_str() {
"u8" => Format::U8,
"u16" => Format::U16,
"u32" => Format::U32,
"u64" => Format::U64,
"u128" => Format::U128,
"i8" => Format::I8,
"i16" => Format::I16,
"i32" => Format::I32,
"i64" => Format::I64,
"i128" => Format::I128,
"f32" => Format::F32,
"f64" => Format::F64,
"bool" => Format::Bool,
"char" => Format::Char,
"String" => Format::Str,
"Box" => match extract_generic(last_segment) {
Some(inner) => to_type_format(&inner),
None => Format::unknown(),
},
"Option" => match extract_generic(last_segment) {
Some(inner) => Format::Option(Box::new(to_type_format(&inner))),
None => Format::unknown(),
},
"Vec" | "HashSet" | "BTreeSet" => {
match extract_generic(last_segment) {
Some(inner) => Format::Seq(Box::new(to_type_format(&inner))),
None => Format::unknown(),
}
}
}
"HashMap" | "BTreeMap" => {
let generics = extract_generics(last_segment);
if generics.len() == 2 {
let key = to_type_format(&generics[0].to_owned());
let value = to_type_format(&generics[1].to_owned());
Format::Map {
key: Box::new(key),
value: Box::new(value),
"HashMap" | "BTreeMap" => {
let generics = extract_generics(last_segment);
if generics.len() == 2 {
let key = to_type_format(&generics[0].to_owned());
let value = to_type_format(&generics[1].to_owned());
Format::Map {
key: Box::new(key),
value: Box::new(value),
}
} else {
Format::unknown()
}
} else {
Format::unknown()
}
_ => Format::TypeName(ident),
}
_ => Format::TypeName(ident),
}
} else {
Format::unknown()
None => Format::unknown(),
}
}
Type::Tuple(TypeTuple { elems, .. }) => {
Expand Down Expand Up @@ -318,7 +314,7 @@ fn trace_enum(traced: &mut Traced, item: &ItemEnum) {
/// Checks that the name of newly found signal is usable.
fn check_signal_name(name: &str, traced: &Traced) -> Result<(), SetupError> {
if traced.registry.contains_key(name) {
Err(SetupError::DuplicatedSignal(name.to_owned()))?
return Err(SetupError::DuplicatedSignal(name.to_owned()));
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion rust_crate_cli/src/tool/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn apply_rust_template(
rinf_config: &RinfConfig,
) -> Result<(), SetupError> {
if root_dir.join("native").is_dir() {
Err(SetupError::TemplateApplied)?;
return Err(SetupError::TemplateApplied);
}

// Copy basic folders needed for Rust to work.
Expand Down